1 /* 2 * Copyright 2001-2004 Brandon Long 3 * All Rights Reserved. 4 * 5 * ClearSilver Templating System 6 * 7 * This code is made available under the terms of the ClearSilver License. 8 * http://www.clearsilver.net/license.hdf 9 * 10 */ 11 12 #ifndef __CGI_H_ 13 #define __CGI_H_ 1 14 15 #include <stdarg.h> 16 #include "util/neo_err.h" 17 #include "util/neo_hdf.h" 18 #include "cs/cs.h" 19 20 __BEGIN_DECLS 21 22 extern NERR_TYPE CGIFinished; 23 extern NERR_TYPE CGIUploadCancelled; 24 extern NERR_TYPE CGIParseNotHandled; 25 26 /* HACK: Set this value if you want to treat empty CGI Query variables as 27 * non-existant. 28 */ 29 extern int IgnoreEmptyFormVars; 30 31 typedef struct _cgi CGI; 32 33 typedef int (*UPLOAD_CB)(CGI *, int nread, int expected); 34 typedef NEOERR* (*CGI_PARSE_CB)(CGI *, char *method, char *ctype, void *rock); 35 36 struct _cgi_parse_cb 37 { 38 char *method; 39 int any_method; 40 char *ctype; 41 int any_ctype; 42 void *rock; 43 CGI_PARSE_CB parse_cb; 44 struct _cgi_parse_cb *next; 45 }; 46 47 struct _cgi 48 { 49 /* Only public parts of this structure */ 50 void *data; /* you can store your own information here */ 51 HDF *hdf; /* the HDF dataset associated with this CGI */ 52 53 BOOL ignore_empty_form_vars; 54 55 UPLOAD_CB upload_cb; 56 57 int data_expected; 58 int data_read; 59 struct _cgi_parse_cb *parse_callbacks; 60 61 /* For line oriented reading of form-data input. Used during cgi_init 62 * only */ 63 char *buf; 64 int buflen; 65 int readlen; 66 BOOL found_nl; 67 BOOL unget; 68 char *last_start; 69 int last_length; 70 int nl; 71 72 /* this is a list of filepointers pointing at files that were uploaded */ 73 /* Use cgi_filehandle to access these */ 74 ULIST *files; 75 76 /* By default, cgi_parse unlinks uploaded files as it opens them. */ 77 /* If Config.Upload.Unlink is set to 0, the files are not unlinked */ 78 /* and there names are stored in this list. */ 79 /* Use Query.*.FileName to access these */ 80 ULIST *filenames; 81 82 /* keep track of the time between cgi_init and cgi_render */ 83 double time_start; 84 double time_end; 85 }; 86 87 88 /* 89 * Function: cgi_init - Initialize ClearSilver CGI environment 90 * Description: cgi_init initializes the ClearSilver CGI environment, 91 * including creating the HDF data set. It will then import 92 * the standard CGI environment variables into that dataset, 93 * will parse the QUERY_STRING into the data set, and parse 94 * the HTTP_COOKIE into the data set. Note that if the 95 * var xdisplay is in the form data, cgi_init will attempt 96 * to validate the value and launch the configured debugger 97 * on the CGI program. These variables have to be 98 * specified in the hdf_file pointed to by hdf_file. The 99 * default settings do not allow debugger launching for 100 * security reasons. 101 * Input: cgi - a pointer to a CGI pointer 102 * hdf_file - the path to an HDF data set file that will also be 103 * loaded into the dataset. This will likely have to 104 * a be a full path, as the HDF search paths are not 105 * yet set up. Certain things, like 106 * Output: cgi - an allocated CGI struct, including 107 * Return: NERR_PARSE - parse error in CGI input 108 * NERR_NOMEM - unable to allocate memory 109 * NERR_NOT_FOUND - hdf_file doesn't exist 110 */ 111 NEOERR *cgi_init (CGI **cgi, HDF *hdf); 112 113 /* 114 * Function: cgi_parse - Parse incoming CGI data 115 * Description: We split cgi_init into two sections, one that parses 116 * just the basics, and the second is cgi_parse. cgi_parse 117 * is responsible for parsing the entity body of the HTTP 118 * request. This payload is typically only sent (expected) 119 * on POST/PUT requests, but generally this is called on 120 * all incoming requests. This function walks the list of 121 * registered parse callbacks (see cgi_register_parse_cb), 122 * and if none of those matches or handles the request, it 123 * falls back to the builtin handlers: 124 * POST w/ application/x-www-form-urlencoded 125 * POST w/ application/form-data 126 * PUT w/ any content type 127 * In general, if there is no Content-Length, then 128 * cgi_parse ignores the payload and doesn't raise an 129 * error. 130 * Input: cgi - a pointer to a CGI pointer 131 * Output: Either data populated into files and cgi->hdf, or whatever 132 * other side effects of your own registered callbacks. 133 * Return: NERR_PARSE - parse error in CGI input 134 * NERR_NOMEM - unable to allocate memory 135 * NERR_NOT_FOUND - hdf_file doesn't exist 136 * NERR_IO - error reading HDF file or reading CGI stdin, or 137 * writing data on multipart/form-data file submission 138 * Anything else you raise. 139 */ 140 NEOERR *cgi_parse (CGI *cgi); 141 142 /* 143 * Function: cgi_register_parse_cb - Register a parse callback 144 * Description: The ClearSilver CGI Kit has built-in functionality to handle 145 * the following methods: 146 * GET -> doesn't have any data except query string, which 147 * is processed for all methods 148 * POST w/ application/x-www-form-urlencoded 149 * POST w/ multipart/form-data 150 * processed as RFC2388 data into files and HDF (see 151 * cgi_filehandle()) 152 * PUT (any type) 153 * The entire data chunk is stored as a file, with meta 154 * data in HDF (similar to single files in RFC2388). 155 * The data is accessible via cgi_filehandle with NULL 156 * for name. 157 * To handle other methods/content types, you have to 158 * register your own parse function. This isn't necessary 159 * if you aren't expecting any data, and technically HTTP 160 * only allows data on PUT/POST requests (and presumably 161 * user defined methods). In particular, if you want to 162 * implement XML-RPC or SOAP, you'll have to register a 163 * callback here to grab the XML data chunk. Usually 164 * you'll want to register POST w/ application/xml or POST 165 * w/ text/xml (you either need to register both or 166 * register POST w/ * and check the ctype yourself, 167 * remember to nerr_raise(CGIParseNotHandled) if you aren't 168 * handling the POST). 169 * In general, your callback should: 170 * Find out how much data is available: 171 * l = hdf_get_value (cgi->hdf, "CGI.ContentLength", NULL); 172 * len = atoi(l); 173 * And read/handle all of the data using cgiwrap_read. 174 * See the builtin handlers for how this is done. Note 175 * that cgiwrap_read is not guarunteed to return all of 176 * the data you request (just like fread(3)) since it 177 * might be reading of a socket. Sorry. 178 * You should be careful when reading the data to watch 179 * for short reads (ie, end of file) and cases where the 180 * client sends you data ad infinitum. 181 * Input: cgi - a CGI struct 182 * method - the HTTP method you want to handle, or * for all 183 * ctype - the HTTP Content-Type you want to handle, or * for all 184 * rock - opaque data that we'll pass to your call back 185 * Output: None 186 * Return: CGIParseNotHandled if your callback doesn't want to handle 187 * this. This causes cgi_parse to continue walking the list of 188 * callbacks. 189 * 190 */ 191 NEOERR *cgi_register_parse_cb(CGI *cgi, const char *method, const char *ctype, 192 void *rock, CGI_PARSE_CB parse_cb); 193 194 /* 195 * Function: cgi_destroy - deallocate the data associated with a CGI 196 * Description: cgi_destroy will destroy all the data associated with a 197 * CGI, which mostly means the associated HDF and removal 198 * of any files that were uploaded via multipart/form-data. 199 * (Note that even in the event of a crash, these files 200 * will be deleted, as they were unlinked on creation and 201 * only exist because of the open file pointer) 202 * Input: cgi - a pointer to a pointer to a CGI struct 203 * Output: cgi - NULL on output 204 * Return: None 205 */ 206 void cgi_destroy (CGI **cgi); 207 208 /* 209 * Function: cgi_cs_init - initialize CS parser with the CGI defaults 210 * Description: cgi_cs_init initializes a CS parser with the CGI HDF 211 * context, and registers the standard CGI filters 212 * Input: cgi - a pointer a CGI struct allocated with cgi_init 213 * cs - a pointer to a CS struct pointer 214 * Output: cs - the allocated/initialized CS struct 215 * Return: NERR_NOMEM - no memory was available to render the template 216 */ 217 NEOERR *cgi_cs_init(CGI *cgi, CSPARSE **cs); 218 219 /* 220 * Function: cgi_display - render and display the CGI output to the user 221 * Description: cgi_display will render the CS template pointed to by 222 * cs_file using the CGI's HDF data set, and send the 223 * output to the user. Note that the output is actually 224 * rendered into memory first. 225 * Input: cgi - a pointer a CGI struct allocated with cgi_init 226 * cs_file - a ClearSilver template file 227 * Output: None 228 * Return: NERR_IO - an IO error occured during output 229 * NERR_NOMEM - no memory was available to render the template 230 */ 231 NEOERR *cgi_display (CGI *cgi, const char *cs_file); 232 233 /* 234 * Function: cgi_output - display the CGI output to the user 235 * Description: Normally, this is called by cgi_display, but some 236 * people wanted it external so they could call it 237 * directly. 238 * Input: cgi - a pointer a CGI struct allocated with cgi_init 239 * output - the data to send to output from the CGI 240 * Output: None 241 * Return: NERR_IO - an IO error occured during output 242 * NERR_NOMEM - no memory was available to render the template 243 */ 244 NEOERR *cgi_output (CGI *cgi, STRING *output); 245 246 /* 247 * Function: cgi_filehandle - return a file pointer to an uploaded file 248 * Description: cgi_filehandle will return the stdio FILE pointer 249 * associated with a file that was uploaded using 250 * multipart/form-data. The FILE pointer is positioned at 251 * the start of the file when first available. 252 * Input: cgi - a pointer to a CGI struct allocated with cgi_init 253 * form_name - the form name that the file was uploaded as 254 * (not the filename) (if NULL, we're asking for the 255 * file handle for the PUT upload) 256 * Output: None 257 * Return: A stdio FILE pointer, or NULL if an error occurs (usually 258 * indicates that the form_name wasn't found, but might indicate 259 * a problem with the HDF dataset) 260 */ 261 FILE *cgi_filehandle (CGI *cgi, const char *form_name); 262 263 /* 264 * Function: cgi_neo_error - display a NEOERR call backtrace 265 * Description: cgi_neo_error will output a 500 error containing the 266 * NEOERR call backtrace. This function is likely to be 267 * removed from future versions in favor of some sort of 268 * user error mechanism. 269 * Input: cgi - a pointer to a CGI struct 270 * err - a NEOERR (see util/neo_err.h for details) 271 * Output: None 272 * Return: None 273 */ 274 void cgi_neo_error (CGI *cgi, NEOERR *err); 275 276 /* 277 * Function: cgi_error - display an error string to the user 278 * Description: cgi_error will output a 500 error containing the 279 * specified error message. This function is likely to be 280 * removed from future versions in favor of a user error 281 * mechanism. 282 * Input: cgi - a pointer to a CGI struct 283 * fmt - printf style format string and arguments 284 * Output: None 285 * Return: None 286 */ 287 void cgi_error (CGI *cgi, const char *fmt, ...) 288 ATTRIBUTE_PRINTF(2,3); 289 290 /* 291 * Function: cgi_debug_init - initialize standalone debugging 292 * Description: cgi_debug_init initializes a CGI program for standalone 293 * debugging. By running a ClearSilver CGI program with a 294 * filename on the command line as the first argument, the 295 * CGI program will load that file of the form K=V as a set 296 * of HTTP/CGI environment variables. This allows you to 297 * run the program under a debugger in a reproducible 298 * environment. 299 * Input: argc/argv - the arguments from main 300 * Output: None 301 * Return: None 302 */ 303 void cgi_debug_init (int argc, char **argv); 304 305 /* 306 * Function: cgi_url_escape - url escape a string 307 * Description: cgi_url_escape will do URL escaping on the passed in 308 * string, and return a newly allocated string that is escaped. 309 * Characters which are escaped include control characters, 310 * %, ?, +, space, =, &, /, and " 311 * Input: buf - a 0 terminated string 312 * Output: esc - a newly allocated string 313 * Return: NERR_NOMEM - no memory available to allocate the escaped string 314 */ 315 NEOERR *cgi_url_escape (const char *buf, char **esc); 316 317 /* 318 * Function: cgi_url_escape_more - url escape a string 319 * Description: cgi_url_escape_more will do URL escaping on the passed in 320 * string, and return a newly allocated string that is escaped. 321 * Characters which are escaped include control characters, 322 * %, ?, +, space, =, &, /, and " and any characters in 323 * other 324 * Input: buf - a 0 terminated string 325 * other - a 0 terminated string of characters to escape 326 * Output: esc - a newly allocated string 327 * Return: NERR_NOMEM - no memory available to allocate the escaped string 328 */ 329 NEOERR *cgi_url_escape_more (const char *buf, char **esc, const char *other); 330 331 /* 332 * Function: cgi_url_validate - validate that url is of an allowed format 333 * Description: cgi_url_validate will check that a URL starts with 334 * one of the accepted safe schemes. 335 * If not, it returns "#" as a safe substitute. 336 * Currently accepted schemes are http, https, ftp and mailto. 337 * It then html escapes the entire URL so that it is safe to 338 * insert in an href attribute. 339 * Input: buf - a 0 terminated string 340 * Output: esc - a newly allocated string 341 * Return: NERR_NOMEM - no memory available to allocate the escaped string 342 */ 343 NEOERR *cgi_url_validate (const char *buf, char **esc); 344 345 /* 346 * Function: cgi_url_unescape - unescape an url encoded string 347 * Description: cgi_url_unescape will do URL unescaping on the passed in 348 * string. This function modifies the string in place 349 * This function will decode any %XX character, and will 350 * decode + as space 351 * Input: buf - a 0 terminated string 352 * Return: pointer to same buf 353 */ 354 char *cgi_url_unescape (char *buf); 355 356 /* 357 * Function: cgi_redirect - send an HTTP 302 redirect response 358 * Description: cgi_redirect will redirect the user to another page on 359 * your site. This version takes only the path portion of 360 * the URL. As with all printf style commands, you should 361 * not call this with arbitrary input that may contain % 362 * characters, if you are forwarding something directly, 363 * use a format like cgi_redirect (cgi, "%s", buf) 364 * Input: cgi - cgi struct 365 * fmt - printf style format with args 366 * Output: None 367 * Return: None 368 */ 369 void cgi_redirect (CGI *cgi, const char *fmt, ...) 370 ATTRIBUTE_PRINTF(2,3); 371 372 /* 373 * Function: cgi_redirect_uri - send an HTTP 302 redirect response 374 * Description: cgi_redirect_uri will redirect the user to another page on 375 * your site. This version takes the full URL, including 376 * protocol/domain/port/path. 377 * As with all printf style commands, you should 378 * not call this with arbitrary input that may contain % 379 * characters, if you are forwarding something directly, 380 * use a format like cgi_redirect (cgi, "%s", buf) 381 * Input: cgi - cgi struct 382 * fmt - printf style format with args 383 * Output: None 384 * Return: None 385 */ 386 void cgi_redirect_uri (CGI *cgi, const char *fmt, ...) 387 ATTRIBUTE_PRINTF(2,3); 388 389 /* 390 * Function: cgi_vredirect - send an HTTP 302 redirect response 391 * Description: cgi_vredirect is mostly used internally, but can be used 392 * if you need a varargs version of the function. 393 * Input: cgi - cgi struct 394 * uri - whether the URL is full (1) or path only (0) 395 * fmt - printf format string 396 * ap - stdarg va_list 397 * Output: None 398 * Return: None 399 */ 400 void cgi_vredirect (CGI *cgi, int uri, const char *fmt, va_list ap); 401 402 403 /* 404 * Function: cgi_cookie_authority - determine the cookie authority for a 405 * domain 406 * Description: cgi_cookie_authority will walk the CookieAuthority 407 * portion of the CGI HDF data set, and return the matching 408 * domain if it exists. The purpose of this is so that you 409 * set domain specific cookies. For instance, you might 410 * have 411 * CookieAuthority.0 = neotonic.com 412 * In which case, any webserver using a hostname ending in 413 * neotonic.com will generate a cookie authority of 414 * neotonic.com. 415 * Input: cgi - a CGI struct 416 * host - optional host to match against. If NULL, the function 417 * will use the HTTP.Host HDF variable. 418 * Output: None 419 * Return: The authority domain, or NULL if none found. 420 */ 421 char *cgi_cookie_authority (CGI *cgi, const char *host); 422 423 /* 424 * Function: cgi_cookie_set - Set a browser Cookie 425 * Description: cgi_cookie_set will issue a Set-Cookie header that 426 * should cause a browser to return a cookie when required. 427 * Note this function does no escaping of anything, you 428 * have to take care of that first. 429 * Input: cgi - a CGI struct 430 * name - the name of the cookie 431 * value - the value to set the cookie to. 432 * path - optional path for which the cookie is valid. Default 433 * is / 434 * domain - optional domain for which the cookie is valid. You 435 * can use cgi_cookie_authority to determine this 436 * domain. Default is none, which is interpreted by 437 * the browser as the sending domain only. 438 * time_str - expiration time string in the following format 439 * Wdy, DD-Mon-YYYY HH:MM:SS GMT. Only used if 440 * persistent. Default is one year from time of call. 441 * persistent - cookie will be stored by the browser between sessions 442 * secure - cookie will only be sent over secure connections 443 * Output: None 444 * Return: NERR_IO 445 */ 446 NEOERR *cgi_cookie_set (CGI *cgi, const char *name, const char *value, 447 const char *path, const char *domain, 448 const char *time_str, int persistent, int secure); 449 450 /* 451 * Function: cgi_cookie_clear - clear browser cookie 452 * Description: cgi_cookie_clear will send back a Set-Cookie string that 453 * will attempt to stop a browser from continuing to send 454 * back a cookie. Note that the cookie has to match in 455 * name, domain, and path, and the luck of the Irish has to 456 * be with you for this work all the time, but at the least 457 * it will make the browser send back a cookie with no 458 * value, which the ClearSilver cookie parsing code will 459 * ignore. 460 * Input: cgi - a CGI struct 461 * name - the cookie name to clear 462 * domain - the domain to clear, NULL for none 463 * path - the cookie's path 464 * Output: None 465 * Return: NERR_IO 466 */ 467 NEOERR *cgi_cookie_clear (CGI *cgi, const char *name, const char *domain, 468 const char *path); 469 470 /* not documented *yet* */ 471 NEOERR *cgi_text_html_strfunc(const char *str, char **ret); 472 NEOERR *cgi_html_strip_strfunc(const char *str, char **ret); 473 NEOERR *cgi_html_escape_strfunc(const char *str, char **ret); 474 NEOERR *cgi_js_escape (const char *buf, char **esc); 475 void cgi_html_ws_strip(STRING *str, int level); 476 NEOERR *cgi_register_strfuncs(CSPARSE *cs); 477 478 /* internal use only */ 479 NEOERR * parse_rfc2388 (CGI *cgi); 480 NEOERR * open_upload(CGI *cgi, int unlink_files, FILE **fpw); 481 482 __END_DECLS 483 484 #endif /* __CGI_H_ */ 485