Make all components of the URI individually optional,
authorschwarze <schwarze@openbsd.org>
Mon, 11 Jul 2016 22:46:57 +0000 (22:46 +0000)
committerschwarze <schwarze@openbsd.org>
Mon, 11 Jul 2016 22:46:57 +0000 (22:46 +0000)
independent of each other, as in:
http://man.openbsd.org[/manpath][/mansec][/arch]/name[.sec]
The restrictions in the past kept confusing people.
Triggered by a question from RafaelNeves at gmail dot com.

usr.bin/mandoc/cgi.c
usr.bin/mandoc/man.cgi.8

index f11ca89..79b42e6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cgi.c,v 1.73 2016/07/10 10:03:15 schwarze Exp $ */
+/*     $OpenBSD: cgi.c,v 1.74 2016/07/11 22:46:57 schwarze Exp $ */
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@usta.de>
@@ -1062,11 +1062,13 @@ main(void)
 static void
 parse_path_info(struct req *req, const char *path)
 {
-       char    *dir;
+       char    *dir[4];
+       int      i;
 
        req->isquery = 0;
        req->q.equal = 1;
        req->q.manpath = mandoc_strdup(path);
+       req->q.arch = NULL;
 
        /* Mandatory manual page name. */
        if ((req->q.query = strrchr(req->q.manpath, '/')) == NULL) {
@@ -1085,27 +1087,50 @@ parse_path_info(struct req *req, const char *path)
        }
 
        /* Handle the case of name[.section] only. */
-       if (req->q.manpath == NULL) {
-               req->q.arch = NULL;
+       if (req->q.manpath == NULL)
                return;
-       }
        req->q.query = mandoc_strdup(req->q.query);
 
-       /* Optional architecture. */
-       dir = strrchr(req->q.manpath, '/');
-       if (dir != NULL && strncmp(dir + 1, "man", 3) != 0) {
-               *dir++ = '\0';
-               req->q.arch = mandoc_strdup(dir);
-               dir = strrchr(req->q.manpath, '/');
-       } else
-               req->q.arch = NULL;
+       /* Split directory components. */
+       dir[i = 0] = req->q.manpath;
+       while ((dir[i + 1] = strchr(dir[i], '/')) != NULL) {
+               if (++i == 3) {
+                       pg_error_badrequest(
+                           "You specified too many directory components.");
+                       exit(EXIT_FAILURE);
+               }
+               *dir[i]++ = '\0';
+       }
+
+       /* Optional manpath. */
+       if ((i = validate_manpath(req, req->q.manpath)) == 0)
+               req->q.manpath = NULL;
+       else if (dir[1] == NULL)
+               return;
 
-       /* Optional directory name. */
-       if (dir != NULL && strncmp(dir + 1, "man", 3) == 0) {
-               *dir++ = '\0';
+       /* Optional section. */
+       if (strncmp(dir[i], "man", 3) == 0) {
                free(req->q.sec);
-               req->q.sec = mandoc_strdup(dir + 3);
+               req->q.sec = mandoc_strdup(dir[i++] + 3);
        }
+       if (dir[i] == NULL) {
+               if (req->q.manpath == NULL)
+                       free(dir[0]);
+               return;
+       }
+       if (dir[i + 1] != NULL) {
+               pg_error_badrequest(
+                   "You specified an invalid directory component.");
+               exit(EXIT_FAILURE);
+       }
+
+       /* Optional architecture. */
+       if (i) {
+               req->q.arch = mandoc_strdup(dir[i]);
+               if (req->q.manpath == NULL)
+                       free(dir[0]);
+       } else
+               req->q.arch = dir[0];
 }
 
 /*
index 71c01c4..eb8a158 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: man.cgi.8,v 1.18 2016/07/10 10:03:15 schwarze Exp $
+.\"    $OpenBSD: man.cgi.8,v 1.19 2016/07/11 22:46:57 schwarze Exp $
 .\"
 .\" Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: July 10 2016 $
+.Dd $Mdocdate: July 11 2016 $
 .Dt MAN.CGI 8
 .Os
 .Sh NAME
@@ -252,7 +252,9 @@ and the name of the requested file, for example
 .Pa /OpenBSD-current/man1/mandoc.1 .
 This can be abbreviated according to the following syntax:
 .Sm off
-.Op / Ar manpath Oo / Cm man Ar sec Oc Op / Ar arch
+.Op / Ar manpath
+.Op / Cm man Ar sec
+.Op / Ar arch
 .Pf / Ar name Op \&. Ar sec
 .Sm on
 .It