#! /bin/sh /usr/share/dpatch/dpatch-run ## 01_local_usermanual.dpatch by Roland Rosenfeld ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Add new "cgi" user-manual, which sends the user manual to the client ## DP: and activate it in config file (Closes: #148128). @DPATCH@ diff -urNad privoxy~/cgi.c privoxy/cgi.c --- privoxy~/cgi.c 2006-02-11 23:44:26.000000000 +0100 +++ privoxy/cgi.c 2006-02-11 23:44:34.000000000 +0100 @@ -609,6 +609,9 @@ { "t", cgi_transparent_image, NULL, TRUE /* Send a transparent image (short name) */ }, + { "user-manual", + cgi_send_user_manual, + NULL, TRUE /* Send user-manual */ }, { NULL, /* NULL Indicates end of list and default page */ cgi_error_404, NULL, TRUE /* Unknown CGI page */ } @@ -821,21 +824,28 @@ { return cgi_error_memory(); } - query_args_start = path_copy; - while (*query_args_start && *query_args_start != '?') + while (*query_args_start && *query_args_start != '?' && *query_args_start != '/') { query_args_start++; } - if (*query_args_start == '?') + if (*query_args_start == '/') { *query_args_start++ = '\0'; - } - - if (NULL == (param_list = parse_cgi_parameters(query_args_start))) - { - free(path_copy); - return cgi_error_memory(); + if ((param_list = new_map())) + { + map(param_list, "file", 1, url_decode(query_args_start), 0); + } + } else { + if (*query_args_start == '?') + { + *query_args_start++ = '\0'; + } + if (NULL == (param_list = parse_cgi_parameters(query_args_start))) + { + free(path_copy); + return cgi_error_memory(); + } } /* @@ -1597,7 +1607,13 @@ if (!item) return NULL; result = strdup("usermanual); + if (config->usermanual[0] == '/') { + string_append(&result, "http://"); + string_append(&result, CGI_SITE_2_HOST); + string_append(&result, "/user-manual/"); + } else { + string_append(&result, config->usermanual); + } string_append(&result, ACTIONS_HELP_PREFIX); string_join (&result, string_toupper(item)); string_append(&result, "\">"); @@ -2171,7 +2187,11 @@ if (!err) err = map(exports, "default-cgi", 1, html_encode(CGI_PREFIX), 0); if (!err) err = map(exports, "menu", 1, make_menu(caller), 0); if (!err) err = map(exports, "code-status", 1, CODE_STATUS, 1); - if (!err) err = map(exports, "user-manual", 1, csp->config->usermanual ,1); + if (csp->config->usermanual[0] == '/') { + if (!err) err = map(exports, "user-manual", 1, "http://"CGI_SITE_2_HOST"/user-manual/" ,1); + } else { + if (!err) err = map(exports, "user-manual", 1, csp->config->usermanual ,1); + } if (!err) err = map(exports, "actions-help-prefix", 1, ACTIONS_HELP_PREFIX ,1); #ifdef FEATURE_TOGGLE if (!err) err = map_conditional(exports, "enabled-display", global_toggle_state); diff -urNad privoxy~/cgisimple.c privoxy/cgisimple.c --- privoxy~/cgisimple.c 2006-02-11 23:44:26.000000000 +0100 +++ privoxy/cgisimple.c 2006-02-11 23:44:34.000000000 +0100 @@ -642,6 +642,89 @@ return JB_ERR_OK; } +/********************************************************************* + * + * Function : cgi_send_user_manual + * + * Description : CGI function that sends a user manual HTML file + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * 2 : rsp = http_response data structure for output + * 3 : parameters = map of cgi parameters + * + * CGI Parameters : file=name.html, the mane of the HTML file + * (relative to user-manual from config) + * + * Returns : JB_ERR_OK on success + * JB_ERR_MEMORY on out-of-memory error. + * + *********************************************************************/ +jb_err cgi_send_user_manual(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters) +{ + const char * filename; + char *full_path; + FILE *fp; + char buf[BUFFER_SIZE]; + + assert(csp); + assert(rsp); + assert(parameters); + + get_string_param(parameters, "file", &filename); + /* Check paramter for hack attempts */ + if (filename && strchr(filename, '/')) { + return JB_ERR_CGI_PARAMS; + } + if (filename && strstr(filename, "..")) { + return JB_ERR_CGI_PARAMS; + } + + full_path = make_path(csp->config->usermanual, + filename?filename:"index.html"); + if (full_path == NULL) + { + return JB_ERR_MEMORY; + } + + /* Allocate buffer */ + rsp->body = strdup(""); + if (rsp->body == NULL) + { + free(full_path); + return JB_ERR_MEMORY; + } + + /* Open user-manual file */ + if (NULL == (fp = fopen(full_path, "r"))) + { + log_error(LOG_LEVEL_ERROR, "Cannot open user-manual file %s: %E", full_path); + free(full_path); + free(rsp->body); + return JB_ERR_FILE; + } + free(full_path); + + /* Read file and write it out */ + while (fgets(buf, BUFFER_SIZE, fp)) + { + if (string_append(&rsp->body, buf)) + { + fclose(fp); + return JB_ERR_MEMORY; + } + } + fclose(fp); + + if (enlist(rsp->headers, "Content-Type: text/html")) + { + return JB_ERR_MEMORY; + } + + return JB_ERR_OK; +} /********************************************************************* diff -urNad privoxy~/cgisimple.h privoxy/cgisimple.h --- privoxy~/cgisimple.h 2006-02-11 23:44:26.000000000 +0100 +++ privoxy/cgisimple.h 2006-02-11 23:44:34.000000000 +0100 @@ -128,6 +128,9 @@ extern jb_err cgi_send_stylesheet(struct client_state *csp, struct http_response *rsp, const struct map *parameters); +extern jb_err cgi_send_user_manual(struct client_state *csp, + struct http_response *rsp, + const struct map *parameters); #ifdef FEATURE_GRACEFUL_TERMINATION extern jb_err cgi_die (struct client_state *csp, diff -urNad privoxy~/loadcfg.c privoxy/loadcfg.c --- privoxy~/loadcfg.c 2006-02-11 23:44:26.000000000 +0100 +++ privoxy/loadcfg.c 2006-02-11 23:44:34.000000000 +0100 @@ -1579,7 +1579,13 @@ * link to it's section in the user-manual */ buf = strdup("\n
usermanual); + if (config->usermanual[0] == '/') { + string_append(&buf, "http://"); + string_append(&buf, CGI_SITE_2_HOST); + string_append(&buf, "/user-manual/"); + } else { + string_append(&buf, config->usermanual); + } string_append(&buf, CONFIG_HELP_PREFIX); string_join (&buf, string_toupper(command)); string_append(&buf, "\">");