URI: 
       Fix relative printelem with ? in name. - geomyidae - A small C-based gopherd.
  HTML git clone git://bitreich.org/geomyidae/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/geomyidae/
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
   DIR commit 6f22091df20685c8b7a8a89823aa31606bea2be0
   DIR parent 42b52f54ede822d8e937025394d69702d5f910d3
  HTML Author: Christoph Lohmann <20h@r-36.net>
       Date:   Sun,  4 Apr 2021 20:57:28 +0200
       
       Fix relative printelem with ? in name.
       
       * Thanks adc for reporting.
       
       * Add more comments in special selector request casing.
       
       Diffstat:
         M ind.c                               |      36 +++++++++++++++++++++-----------
         M main.c                              |      12 ++++++++++--
       
       2 files changed, 34 insertions(+), 14 deletions(-)
       ---
   DIR diff --git a/ind.c b/ind.c
       @@ -403,8 +403,8 @@ scanfile(char *fname)
        int
        printelem(int fd, Elems *el, char *file, char *base, char *addr, char *port)
        {
       -        char *path, *p, buf[PATH_MAX+1];
       -        int len;
       +        char *path, *p, *argbase, buf[PATH_MAX+1];
       +        int len, blen;
        
                if (!strcmp(el->e[3], "server")) {
                        free(el->e[3]);
       @@ -417,24 +417,36 @@ printelem(int fd, Elems *el, char *file, char *base, char *addr, char *port)
        
                /*
                 * Ignore if the path is from base, if it might be some h type with
       -         * some URL and ignore various types that have different semantics but
       -         * to point to some file or directory.
       +         * some URL and ignore various types that have different semantics,
       +         * do not point to some file or directory.
       +         */
       +        /*
       +         * FUTURE: If ever special requests with no beginning '/' are used in
       +         * geomyidae, this is the place to control this.
                 */
                if ((el->e[2][0] != '\0'
       -            && el->e[2][0] != '/'
       -            && el->e[0][0] != 'i'
       -            && el->e[0][0] != '2'
       -            && el->e[0][0] != '3'
       -            && el->e[0][0] != '8'
       -            && el->e[0][0] != 'w'
       -            && el->e[0][0] != 'T') &&
       +            && el->e[2][0] != '/' /* Absolute Request. */
       +            && el->e[0][0] != 'i' /* Informational item. */
       +            && el->e[0][0] != '2' /* CSO server */
       +            && el->e[0][0] != '3' /* Error */
       +            && el->e[0][0] != '8' /* Telnet */
       +            && el->e[0][0] != 'w' /* Selector is direct URI. */
       +            && el->e[0][0] != 'T') && /* tn3270 */
                    !(el->e[0][0] == 'h' && !strncmp(el->e[2], "URL:", 4))) {
                        path = file + strlen(base);
                        if ((p = strrchr(path, '/')))
                                len = p - path;
                        else
                                len = strlen(path);
       -                snprintf(buf, sizeof(buf), "%s%.*s/%s", base, len, path, el->e[2]);
       +
       +                argbase = strchr(el->e[2], '?');
       +                if (argbase != NULL)
       +                        blen = argbase - el->e[2];
       +                else
       +                        blen = strlen(el->e[2]);
       +
       +                snprintf(buf, sizeof(buf), "%s%.*s/%.*s", base, len,
       +                        path, blen, el->e[2]);
        
                        if ((path = realpath(buf, NULL)) &&
                                        !strncmp(base, path, strlen(base))) {
   DIR diff --git a/main.c b/main.c
       @@ -177,6 +177,7 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost,
        
                memmove(recvc, recvb, rlen+1);
        
       +        /* Redirect to HTML redirecting to the specified URI. */
                if (!strncmp(recvb, "URL:", 4)) {
                        len = snprintf(path, sizeof(path), htredir,
                                        recvb + 4, recvb + 4, recvb + 4);
       @@ -189,8 +190,8 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost,
                }
        
                /*
       -         * Valid cases in gopher we overwrite here, but could be used for
       -         * other geomyidae features:
       +         * FUTURE: Valid cases in gopher we overwrite here, but could be used
       +         * for other geomyidae features:
                 *
                 *        request string = "?..." -> "/?..."
                 *        request string = "" -> "/"
       @@ -198,6 +199,9 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost,
                 *
                 * Be careful, when you consider those special cases to be used
                 * for some feature. You can easily do good and bad.
       +         *
       +         * Look at printelem() in ind.c for the counterpart of producing
       +         * selectors.
                 */
        
                args = strchr(recvb, '?');
       @@ -209,6 +213,10 @@ handlerequest(int sock, char *req, int rlen, char *base, char *ohost,
                        recvb[1] = '\0';
                }
        
       +        /*
       +         * Do not allow requests not beginning with '/' or which contain
       +         * "..".
       +         */
                if (recvb[0] != '/' || strstr(recvb, "..")){
                        dprintf(sock, "%s", selinval);
                        return;