aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2016-03-17 21:22:59 +0000
committerIngo Schwarze <schwarze@openbsd.org>2016-03-17 21:22:59 +0000
commit073faa9daabed86280f98fdf6e03c930b0c97d71 (patch)
tree07eaf356556f7f9c42eb3275dd1dde7074e86992
parentf0aaaf5ca33c0d2fda4d44a60eeb07936efdfe8a (diff)
downloadmandoc-073faa9daabed86280f98fdf6e03c930b0c97d71.tar.gz
mandoc-073faa9daabed86280f98fdf6e03c930b0c97d71.tar.zst
mandoc-073faa9daabed86280f98fdf6e03c930b0c97d71.zip
support short URIs for man.openbsd.org
-rw-r--r--cgi.c78
1 files changed, 69 insertions, 9 deletions
diff --git a/cgi.c b/cgi.c
index 0b01d066..cb041b68 100644
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-/* $Id: cgi.c,v 1.116 2016/01/04 12:36:26 schwarze Exp $ */
+/* $Id: cgi.c,v 1.117 2016/03/17 21:22:59 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@usta.de>
@@ -64,6 +64,7 @@ static void html_putchar(char);
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 *);
@@ -1033,11 +1034,21 @@ main(void)
memset(&req, 0, sizeof(struct req));
pathgen(&req);
- /* Next parse out the query string. */
+ /* Parse the path info and the query string. */
- if (NULL != (querystring = getenv("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)) {
@@ -1054,12 +1065,6 @@ main(void)
/* 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)
@@ -1078,6 +1083,61 @@ main(void)
}
/*
+ * 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;
+ }
+}
+
+/*
* Scan for indexable paths.
*/
static void