1.\" $Id: man.cgi.3,v 1.4 2017/03/15 13:18:53 schwarze Exp $ 2.\" 3.\" Copyright (c) 2016, 2017 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 $Mdocdate: March 15 2017 $ 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. 129If possible, requests using 130.Ev QUERY_STRING 131are redirected to URIs using 132.Ev PATH_INFO 133by calling 134.Fn pg_redirect . 135Otherwise, it changes into the manpath and calls 136.Xr mansearch 3 . 137Depending on the result, it calls either 138.Fn pg_noresult 139or 140.Fn pg_searchres . 141.It Ft void Fn pg_redirect "const struct req *req" "const char *name" 142This function is special in so far as it does not print an HTML page, 143but only an HTTP 303 response with a Location: of the form: 144.Sm off 145.No http:// 146.Ar host Ns / 147.Op Ar scriptname Ns / 148.Op Ar manpath Ns / 149.Op Ar arch Ns / 150.Fa name 151.Op Pf . Ar sec 152.Sm on 153.It Ft void Fn pg_noresult "const struct req *req" "const char *msg" 154This function calls 155.Fn resp_begin_html , 156.Fn resp_searchform , 157prints the 158.Fa msg 159passed to it, and calls 160.Fn resp_end_html . 161.It Ft void Fn pg_searchres "const struct req *req" "struct manpage *r"\ 162 "size_t sz" 163This function first validates the filenames found. 164If 165.Ev QUERY_STRING 166was used and there is exactly one result, 167it writes an HTTP redirect to that result. 168Otherwise, it writes an HTML result page beginning with 169.Fn resp_begin_html 170and 171.Fn resp_searchform . 172If there is more than one result, it writes a list of links 173to all the results. 174If it was a 175.Xr man 1 176rather than an 177.Xr apropos 1 178query or if there is only one single result, it calls 179.Fn resp_show . 180Finally, it calls 181.Fn resp_end_html . 182.It Ft void Fn pg_index "const struct req *req" 183This page generator is used when 184.Ev PATH_INFO 185and 186.Ev QUERY_STRING 187are both empty. 188It calls 189.Fn resp_begin_html 190and 191.Fn resp_searchform , 192writes links to help pages, and calls 193.Fn resp_end_html . 194.It Ft void Fn pg_error_badrequest "const char *msg" 195This page generator is used when 196.Fn main 197or 198.Fn pg_show 199detect an invalid URI. 200It calls 201.Fn resp_begin_html , 202prints the 203.Fa msg 204provided, and calls 205.Fn resp_end_html . 206.It Ft void Fn pg_error_internal void 207This page generator is used by various functions when errors are 208detected in the 209.Pa manpath.conf 210configuration file, in 211.Xr mandoc.db 5 212databases, in the 213.Xr mandoc 3 214parser, in file system permissions, or when setting up timeouts. 215It calls 216.Fn resp_begin_html , 217prints 218.Qq "Internal Server Error" , 219and calls 220.Fn resp_end_html . 221Before calling 222.Fn pg_error_internal , 223call 224.Xr warn 3 225or 226.Xr warnx 3 227to log the reason of the error to the 228.Xr httpd 8 229server log file. 230.El 231.Ss Result generators 232The purpose of result generators is to print a chunk of HTML code. 233When they print untrusted strings or characters, 234.Fn html_print 235and 236.Fn html_putchar 237are used. 238The highest level result generators are: 239.Bl -tag -width 1n 240.It Ft void Fn resp_begin_html "int code" "const char *msg" "const char *file" 241This generator calls 242.Fn resp_begin_http 243to print the HTTP headers, then prints the HTML header up to the 244opening tag of the <body> element, then copies the file 245.Pa header.html 246to the output, if it exists and is readable. 247If 248.Fa file 249is not 250.Dv NULL , 251it is used for the <title> element. 252.It Ft void Fn resp_searchform "const struct req *req" "enum focus focus" 253This generator prints a search form, filling it with data 254from the provided request object. 255If the 256.Fa focus 257argument is 258.Dv FOCUS_QUERY , 259it sets the document's autofocus to the query input box. 260.It Ft void Fn resp_show "const struct req *req" "const char *file" 261This wrapper dispatches to either 262.Fn resp_catman 263or 264.Fn resp_format , 265depending on whether 266.Ar file 267starts with 268.Pa cat 269or 270.Pa man , 271respectively. 272.It Ft void Fn resp_catman "const struct req *req" "const char *file" 273This generator translates a preformatted, backspace-encoded manual 274page to HTML and prints it to the output. 275.It Ft void Fn resp_format "const struct req *req" "const char *file" 276This generator formats a manual page on the standard output, 277using the functions documented in 278.Xr mchars_alloc 3 279and 280.Xr mandoc 3 . 281.It Ft void Fn resp_end_html void 282This generator copies the file 283.Pa footer.html 284to the output, if it exists and is readable, 285and closes the <body> and <html> elements. 286.El 287.Ss Utility routines 288These functions take a string and return 1 if it is valid, or 0 otherwise. 289.Bl -tag -width 1n 290.It Ft int Fn validate_urifrag "const char *frag" 291Checks that the string only contains alphanumeric ASCII characters, 292dashes, dots, slashes, and underscores. 293.It Ft int Fn validate_manpath "const struct req *req" "const char* manpath" 294Checks that the string is either 295.Qq mandoc 296or one of the manpaths configured in 297.Pa manpath.conf . 298.It Ft int Fn validate_filename "const char *file" 299Checks that the string starts with 300.Qq man 301or 302.Qq cat 303and does not ascend to parent directories. 304.El 305.Sh SEE ALSO 306.Xr mandoc 3 , 307.Xr mansearch 3 , 308.Xr mchars_alloc 3 , 309.Xr mandoc.db 5 , 310.Xr man.cgi 8 311