=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mandoc/cgi.c,v retrieving revision 1.55 retrieving revision 1.56 diff -c -r1.55 -r1.56 *** src/usr.bin/mandoc/cgi.c 2015/12/25 20:16:19 1.55 --- src/usr.bin/mandoc/cgi.c 2016/03/17 21:22:43 1.56 *************** *** 1,4 **** ! /* $OpenBSD: cgi.c,v 1.55 2015/12/25 20:16:19 bentley Exp $ */ /* * Copyright (c) 2011, 2012 Kristaps Dzonsons * Copyright (c) 2014, 2015 Ingo Schwarze --- 1,4 ---- ! /* $OpenBSD: cgi.c,v 1.56 2016/03/17 21:22:43 schwarze Exp $ */ /* * Copyright (c) 2011, 2012 Kristaps Dzonsons * Copyright (c) 2014, 2015 Ingo Schwarze *************** *** 62,67 **** --- 62,68 ---- static int http_decode(char *); static void http_parse(struct req *, const char *); static void pathgen(struct req *); + static void path_parse(struct req *req, const char *path); static void pg_error_badrequest(const char *); static void pg_error_internal(void); static void pg_index(const struct req *); *************** *** 1031,1041 **** memset(&req, 0, sizeof(struct req)); pathgen(&req); ! /* Next parse out the query string. */ ! if (NULL != (querystring = getenv("QUERY_STRING"))) http_parse(&req, querystring); if (req.q.manpath == NULL) req.q.manpath = mandoc_strdup(req.p[0]); else if ( ! validate_manpath(&req, req.q.manpath)) { --- 1032,1052 ---- memset(&req, 0, sizeof(struct req)); pathgen(&req); ! /* Parse the path info and the query string. */ ! if ((path = getenv("PATH_INFO")) == NULL) ! path = ""; ! else if (*path == '/') ! path++; ! ! if (*path != '\0' && access(path, F_OK) == -1) { ! path_parse(&req, path); ! path = ""; ! } else if ((querystring = getenv("QUERY_STRING")) != NULL) http_parse(&req, querystring); + /* Validate parsed data and add defaults. */ + if (req.q.manpath == NULL) req.q.manpath = mandoc_strdup(req.p[0]); else if ( ! validate_manpath(&req, req.q.manpath)) { *************** *** 1052,1063 **** /* Dispatch to the three different pages. */ - path = getenv("PATH_INFO"); - if (NULL == path) - path = ""; - else if ('/' == *path) - path++; - if ('\0' != *path) pg_show(&req, path); else if (NULL != req.q.query) --- 1063,1068 ---- *************** *** 1073,1078 **** --- 1078,1138 ---- free(req.p[i]); free(req.p); return EXIT_SUCCESS; + } + + /* + * If PATH_INFO is not a file name, translate it to a query. + */ + static void + path_parse(struct req *req, const char *path) + { + int dir_done; + + req->q.equal = 1; + req->q.manpath = mandoc_strdup(path); + + /* Mandatory manual page name. */ + if ((req->q.query = strrchr(req->q.manpath, '/')) == NULL) { + req->q.query = req->q.manpath; + req->q.manpath = NULL; + } else + *req->q.query++ = '\0'; + + /* Optional trailing section. */ + if ((req->q.sec = strrchr(req->q.query, '.')) != NULL) { + if(isdigit((unsigned char)req->q.sec[1])) { + *req->q.sec++ = '\0'; + req->q.sec = mandoc_strdup(req->q.sec); + } else + req->q.sec = NULL; + } + + /* Handle the case of name[.section] only. */ + if (req->q.manpath == NULL) { + req->q.arch = NULL; + return; + } + req->q.query = mandoc_strdup(req->q.query); + + /* Optional architecture. */ + dir_done = 0; + for (;;) { + if ((req->q.arch = strrchr(req->q.manpath, '/')) == NULL) + break; + *req->q.arch++ = '\0'; + if (dir_done || strncmp(req->q.arch, "man", 3)) { + req->q.arch = mandoc_strdup(req->q.arch); + break; + } + + /* Optional directory name. */ + req->q.arch += 3; + if (*req->q.arch != '\0') { + free(req->q.sec); + req->q.sec = mandoc_strdup(req->q.arch); + } + dir_done = 1; + } } /*