1.\" Id: man.cgi.3,v 1.2 2016/07/07 19:19:01 schwarze Exp 2.\" 3.\" Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org> 4.\" 5.\" Permission to use, copy, modify, and distribute this software for any 6.\" purpose with or without fee is hereby granted, provided that the above 7.\" copyright notice and this permission notice appear in all copies. 8.\" 9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16.\" 17.Dd July 7, 2016 18.Dt MAN.CGI 3 19.Os 20.Sh NAME 21.Nm man.cgi 22.Nd internals of the CGI program to search and display manual pages 23.Sh DESCRIPTION 24The source code of 25.Xr man.cgi 8 26is organized in four levels: 27.Pp 28.Bl -enum -compact 29.It 30.Sx Top level 31.It 32.Sx Page generators 33.It 34.Sx Result generators 35.It 36.Sx Utility routines 37.El 38.Ss Top level 39The top level of 40.Xr man.cgi 8 41consists of the 42.Fn main 43program and a few parser routines. 44.Bl -tag -width 1n 45.It Ft int Fn main void 46The main program 47.Bl -dash -compact 48.It 49limits execution time; 50.It 51changes to 52.Dv MAN_DIR , 53the data directory containing all the manual trees; 54.It 55calls 56.Fn parse_manpath_conf ; 57.It 58if 59.Ev PATH_INFO 60is empty, calls 61.Fn parse_query_string ; 62otherwise, 63calls 64.Fn parse_path_info ; 65.It 66validates the manpath and the architecture; 67.It 68calls the appropriate one among the 69.Sx Page generators . 70.El 71.It Ft void Fn parse_manpath_conf "struct req *req" 72Parses and validates 73.Pa manpath.conf 74and fills 75.Va req->p 76and 77.Va req->psz . 78.It Ft void Fn parse_path_info "struct req *req" "const char *path" 79Parses and validates 80.Ev PATH_INFO , 81clears 82.Va req->isquery , 83and fills 84.Va req->q . 85.It Ft void Fn parse_query_string "struct req *req" "const char *qs" 86Parses and validates 87.Ev QUERY_STRING , 88sets 89.Va req->isquery , 90and fills 91.Va req->q . 92This function is the only user of the utility functions 93.Fn http_decode 94and 95.Fn set_query_attr . 96.El 97.Ss Page generators 98The purpose of each page generator is to print a complete HTML page, 99starting with the HTTP headers and continuing to the page footer. 100Before starting HTML output with 101.Fn resp_begin_html , 102some page generators do some preparatory work, for example to decide 103which page to show. 104Each page generator ends with a call to 105.Fn resp_end_html . 106.Bl -tag -width 1n 107.It Ft void Fn pg_show "struct req *req" "const char *fullpath" 108This page generator is used when 109.Ev PATH_INFO 110contains the complete path to a manual page including manpath, 111section directory, optional architecture subdirectory, manual name 112and section number suffix. 113It validates the manpath, changes into it, validate the filename, 114and then calls 115.Fn resp_begin_html , 116.Fn resp_searchform , 117.Fn resp_show , 118and 119.Fn resp_end_html 120in that order. 121.It Ft void Fn pg_search "const struct req *req" 122This page generator is used when 123.Ev PATH_INFO 124contains a search query in short format or when 125.Ev PATH_INFO 126is empty and a 127.Ev QUERY_STRING 128is provided. 129It changes into the manpath and calls 130.Xr mansearch 3 . 131Depending on the result, it calls either 132.Fn pg_noresult 133or 134.Fn pg_searchres . 135.It Ft void Fn pg_noresult "const struct req *req" "const char *msg" 136This function calls 137.Fn resp_begin_html , 138.Fn resp_searchform , 139prints the 140.Fa msg 141passed to it, and calls 142.Fn resp_end_html . 143.It Ft void Fn pg_searchres "const struct req *req" "struct manpage *r"\ 144 "size_t sz" 145This function first validates the filenames found. 146If 147.Ev QUERY_STRING 148was used and there is exactly one result, 149it writes an HTTP redirect to that result. 150Otherwise, it writes an HTML result page beginning with 151.Fn resp_begin_html 152and 153.Fn resp_searchform . 154If there is more than one result, it writes a list of links 155to all the results. 156If it was a 157.Xr man 1 158rather than an 159.Xr apropos 1 160query or if there is only one single result, it calls 161.Fn resp_show . 162Finally, it calls 163.Fn resp_end_html . 164.It Ft void Fn pg_index "const struct req *req" 165This page generator is used when 166.Ev PATH_INFO 167and 168.Ev QUERY_STRING 169are both empty. 170It calls 171.Fn resp_begin_html 172and 173.Fn resp_searchform , 174writes links to help pages, and calls 175.Fn resp_end_html . 176.It Ft void Fn pg_error_badrequest "const char *msg" 177This page generator is used when 178.Fn main 179or 180.Fn pg_show 181detect an invalid URI. 182It calls 183.Fn resp_begin_html , 184prints the 185.Fa msg 186provided, and calls 187.Fn resp_end_html . 188.It Ft void Fn pg_error_internal void 189This page generator is used by various functions when errors are 190detected in the 191.Pa manpath.conf 192configuration file, in 193.Xr mandoc.db 5 194databases, in the 195.Xr mandoc 3 196parser, in file system permissions, or when setting up timeouts. 197It calls 198.Fn resp_begin_html , 199prints 200.Qq "Internal Server Error" , 201and calls 202.Fn resp_end_html . 203Before calling 204.Fn pg_error_internal , 205call 206.Xr warn 3 207or 208.Xr warnx 3 209to log the reason of the error to the 210.Xr httpd 8 211server log file. 212.El 213.Ss Result generators 214The purpose of result generators is to print a chunk of HTML code. 215When they print untrusted strings or characters, 216.Fn html_print 217and 218.Fn html_putchar 219are used. 220The highest level result generators are: 221.Bl -tag -width 1n 222.It Ft void Fn resp_begin_html "int code" "const char *msg" 223This generator calls 224.Fn resp_begin_http 225to print the HTTP headers, then prints the HTML header up to the 226opening tag of the <body> element, then copies the file 227.Pa header.html 228to the output, if it exists and is readable. 229.It Ft void Fn resp_searchform "const struct req *req" "enum focus focus" 230This generator prints a search form, filling it with data 231from the provided request object. 232If the 233.Fa focus 234argument is 235.Dv FOCUS_QUERY , 236it sets the document's autofocus to the query input box. 237.It Ft void Fn resp_show "const struct req *req" "const char *file" 238This wrapper dispatches to either 239.Fn resp_catman 240or 241.Fn resp_format , 242depending on whether 243.Ar file 244starts with 245.Pa cat 246or 247.Pa man , 248respectively. 249.It Ft void Fn resp_catman "const struct req *req" "const char *file" 250This generator translates a preformatted, backspace-encoded manual 251page to HTML and prints it to the output. 252.It Ft void Fn resp_format "const struct req *req" "const char *file" 253This generator formats a manual page on the standard output, 254using the functions documented in 255.Xr mchars_alloc 3 256and 257.Xr mandoc 3 . 258.It Ft void Fn resp_end_html void 259This generator copies the file 260.Pa footer.html 261to the output, if it exists and is readable, 262and closes the <body> and <html> elements. 263.El 264.Ss Utility routines 265These functions take a string and return 1 if it is valid, or 0 otherwise. 266.Bl -tag -width 1n 267.It Ft int Fn validate_urifrag "const char *frag" 268Checks that the string only contains alphanumeric ASCII characters, 269dashes, dots, slashes, and underscores. 270.It Ft int Fn validate_manpath "const struct req *req" "const char* manpath" 271Checks that the string is either 272.Qq mandoc 273or one of the manpaths configured in 274.Pa manpath.conf . 275.It Ft int Fn validate_filename "const char *file" 276Checks that the string starts with 277.Qq man 278or 279.Qq cat 280and does not ascend to parent directories. 281.El 282.Sh SEE ALSO 283.Xr mandoc 3 , 284.Xr mansearch 3 , 285.Xr mchars_alloc 3 , 286.Xr mandoc.db 5 , 287.Xr man.cgi 8 288