version 1.115, 2015/11/07 17:58:55 |
version 1.117, 2016/03/17 21:22:59 |
Line 63 static void html_print(const char *); |
|
Line 63 static void html_print(const char *); |
|
static void html_putchar(char); |
static void html_putchar(char); |
static int http_decode(char *); |
static int http_decode(char *); |
static void http_parse(struct req *, const char *); |
static void http_parse(struct req *, const char *); |
static void http_print(const char *); |
|
static void http_putchar(char); |
|
static void http_printquery(const struct req *, const char *); |
|
static void pathgen(struct req *); |
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_badrequest(const char *); |
static void pg_error_internal(void); |
static void pg_error_internal(void); |
static void pg_index(const struct req *); |
static void pg_index(const struct req *); |
Line 149 html_putchar(char c) |
|
Line 147 html_putchar(char c) |
|
} |
} |
} |
} |
|
|
static void |
|
http_printquery(const struct req *req, const char *sep) |
|
{ |
|
|
|
if (NULL != req->q.query) { |
|
printf("query="); |
|
http_print(req->q.query); |
|
} |
|
if (0 == req->q.equal) |
|
printf("%sapropos=1", sep); |
|
if (NULL != req->q.sec) { |
|
printf("%ssec=", sep); |
|
http_print(req->q.sec); |
|
} |
|
if (NULL != req->q.arch) { |
|
printf("%sarch=", sep); |
|
http_print(req->q.arch); |
|
} |
|
if (strcmp(req->q.manpath, req->p[0])) { |
|
printf("%smanpath=", sep); |
|
http_print(req->q.manpath); |
|
} |
|
} |
|
|
|
static void |
|
http_print(const char *p) |
|
{ |
|
|
|
if (NULL == p) |
|
return; |
|
while ('\0' != *p) |
|
http_putchar(*p++); |
|
} |
|
|
|
/* |
/* |
* Call through to html_putchar(). |
* Call through to html_putchar(). |
* Accepts NULL strings. |
* Accepts NULL strings. |
|
|
} |
} |
} |
} |
|
|
static void |
|
http_putchar(char c) |
|
{ |
|
|
|
if (isalnum((unsigned char)c)) { |
|
putchar((unsigned char)c); |
|
return; |
|
} else if (' ' == c) { |
|
putchar('+'); |
|
return; |
|
} |
|
printf("%%%.2x", c); |
|
} |
|
|
|
/* |
/* |
* HTTP-decode a string. The standard explanation is that this turns |
* HTTP-decode a string. The standard explanation is that this turns |
* "%4e+foo" into "n foo" in the regular way. This is done in-place |
* "%4e+foo" into "n foo" in the regular way. This is done in-place |
Line 623 pg_searchres(const struct req *req, struct manpage *r, |
|
Line 573 pg_searchres(const struct req *req, struct manpage *r, |
|
* without any delay. |
* without any delay. |
*/ |
*/ |
printf("Status: 303 See Other\r\n"); |
printf("Status: 303 See Other\r\n"); |
printf("Location: http://%s%s/%s/%s?", |
printf("Location: http://%s%s/%s/%s", |
HTTP_HOST, scriptname, req->q.manpath, r[0].file); |
HTTP_HOST, scriptname, req->q.manpath, r[0].file); |
http_printquery(req, "&"); |
|
printf("\r\n" |
printf("\r\n" |
"Content-Type: text/html; charset=utf-8\r\n" |
"Content-Type: text/html; charset=utf-8\r\n" |
"\r\n"); |
"\r\n"); |
Line 640 pg_searchres(const struct req *req, struct manpage *r, |
|
Line 589 pg_searchres(const struct req *req, struct manpage *r, |
|
for (i = 0; i < sz; i++) { |
for (i = 0; i < sz; i++) { |
printf("<TR>\n" |
printf("<TR>\n" |
"<TD CLASS=\"title\">\n" |
"<TD CLASS=\"title\">\n" |
"<A HREF=\"%s/%s/%s?", |
"<A HREF=\"%s/%s/%s", |
scriptname, req->q.manpath, r[i].file); |
scriptname, req->q.manpath, r[i].file); |
http_printquery(req, "&"); |
|
printf("\">"); |
printf("\">"); |
html_print(r[i].names); |
html_print(r[i].names); |
printf("</A>\n" |
printf("</A>\n" |
|
|
memset(&req, 0, sizeof(struct req)); |
memset(&req, 0, sizeof(struct req)); |
pathgen(&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); |
http_parse(&req, querystring); |
|
|
|
/* Validate parsed data and add defaults. */ |
|
|
if (req.q.manpath == NULL) |
if (req.q.manpath == NULL) |
req.q.manpath = mandoc_strdup(req.p[0]); |
req.q.manpath = mandoc_strdup(req.p[0]); |
else if ( ! validate_manpath(&req, req.q.manpath)) { |
else if ( ! validate_manpath(&req, req.q.manpath)) { |
|
|
|
|
/* Dispatch to the three different pages. */ |
/* Dispatch to the three different pages. */ |
|
|
path = getenv("PATH_INFO"); |
|
if (NULL == path) |
|
path = ""; |
|
else if ('/' == *path) |
|
path++; |
|
|
|
if ('\0' != *path) |
if ('\0' != *path) |
pg_show(&req, path); |
pg_show(&req, path); |
else if (NULL != req.q.query) |
else if (NULL != req.q.query) |
|
|
free(req.p[i]); |
free(req.p[i]); |
free(req.p); |
free(req.p); |
return EXIT_SUCCESS; |
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; |
|
} |
} |
} |
|
|
/* |
/* |