=================================================================== RCS file: /cvs/mandoc/cgi.c,v retrieving revision 1.143 retrieving revision 1.149 diff -u -p -r1.143 -r1.149 --- mandoc/cgi.c 2017/01/19 13:55:56 1.143 +++ mandoc/cgi.c 2017/03/15 10:17:29 1.149 @@ -1,4 +1,4 @@ -/* $Id: cgi.c,v 1.143 2017/01/19 13:55:56 schwarze Exp $ */ +/* $Id: cgi.c,v 1.149 2017/03/15 10:17:29 schwarze Exp $ */ /* * Copyright (c) 2011, 2012 Kristaps Dzonsons * Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze @@ -21,7 +21,9 @@ #include #include +#if HAVE_ERR #include +#endif #include #include #include @@ -74,6 +76,7 @@ static void pg_error_badrequest(const char *); static void pg_error_internal(void); static void pg_index(const struct req *); static void pg_noresult(const struct req *, const char *); +static void pg_redirect(const struct req *, const char *); static void pg_search(const struct req *); static void pg_searchres(const struct req *, struct manpage *, size_t); @@ -113,7 +116,7 @@ static const char *const sec_names[] = { static const int sec_MAX = sizeof(sec_names) / sizeof(char *); static const char *const arch_names[] = { - "amd64", "alpha", "armv7", + "amd64", "alpha", "armv7", "arm64", "hppa", "i386", "landisk", "loongson", "luna88k", "macppc", "mips64", "octeon", "sgi", "socppc", "sparc64", @@ -494,9 +497,9 @@ pg_index(const struct req *req) resp_searchform(req, FOCUS_QUERY); printf("

\n" "This web interface is documented in the\n" - "man.cgi(8)\n" + "man.cgi(8)\n" "manual, and the\n" - "apropos(1)\n" + "apropos(1)\n" "manual explains the query syntax.\n" "

\n", scriptname, *scriptname == '\0' ? "" : "/", @@ -538,6 +541,23 @@ pg_error_internal(void) } static void +pg_redirect(const struct req *req, const char *name) +{ + printf("Status: 303 See Other\r\n"); + printf("Location: http://%s/", HTTP_HOST); + if (*scriptname != '\0') + printf("%s/", scriptname); + if (strcmp(req->q.manpath, req->p[0])) + printf("%s/", req->q.manpath); + if (req->q.arch != NULL) + printf("%s/", req->q.arch); + printf("%s", name); + if (req->q.sec != NULL) + printf(".%s", req->q.sec); + printf("\r\nContent-Type: text/html; charset=utf-8\r\n\r\n"); +} + +static void pg_searchres(const struct req *req, struct manpage *r, size_t sz) { char *arch, *archend; @@ -576,26 +596,21 @@ pg_searchres(const struct req *req, struct manpage *r, req->q.equal || sz == 1 ? FOCUS_NONE : FOCUS_QUERY); if (sz > 1) { - puts("
"); - puts(""); - + puts("
"); for (i = 0; i < sz; i++) { printf(" \n" - " \n" - " \n" + puts("\n" " "); } - - puts("
" - "" + "", scriptname, *scriptname == '\0' ? "" : "/", req->q.manpath, r[i].file); - printf("\">"); html_print(r[i].names); printf(""); + " "); html_print(r[i].output); - puts("
\n" - "
"); + puts(""); } /* @@ -804,6 +819,7 @@ resp_format(const struct req *req, const char *file) memset(&conf, 0, sizeof(conf)); conf.fragment = 1; + conf.style = mandoc_strdup(CSS_DIR "/mandoc.css"); usepath = strcmp(req->q.manpath, req->p[0]); mandoc_asprintf(&conf.man, "/%s%s%%N.%%S", usepath ? req->q.manpath : "", usepath ? "/" : ""); @@ -831,6 +847,7 @@ resp_format(const struct req *req, const char *file) mparse_free(mp); mchars_free(); free(conf.man); + free(conf.style); } static void @@ -957,9 +974,13 @@ pg_search(const struct req *req) } } - if (0 == mansearch(&search, &paths, argc, argv, &res, &ressz)) + res = NULL; + ressz = 0; + if (req->isquery && req->q.equal && argc == 1) + pg_redirect(req, argv[0]); + else if (mansearch(&search, &paths, argc, argv, &res, &ressz) == 0) pg_noresult(req, "You entered an invalid query."); - else if (0 == ressz) + else if (ressz == 0) pg_noresult(req, "No results found."); else pg_searchres(req, res, ressz); @@ -978,6 +999,22 @@ main(void) const char *path; const char *querystring; int i; + +#if HAVE_PLEDGE + /* + * The "rpath" pledge could be revoked after mparse_readfd() + * if the file desciptor to "/footer.html" would be opened + * up front, but it's probably not worth the complication + * of the code it would cause: it would require scattering + * pledge() calls in multiple low-level resp_*() functions. + */ + + if (pledge("stdio rpath", NULL) == -1) { + warn("pledge"); + pg_error_internal(); + return EXIT_FAILURE; + } +#endif /* Poor man's ReDoS mitigation. */