Suppress edit buttons for action files if Privoxy has
[privoxy.git] / cgi.c
diff --git a/cgi.c b/cgi.c
index da9d087..b9863c7 100644 (file)
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-const char cgi_rcs[] = "$Id: cgi.c,v 1.78 2006/09/21 19:22:07 fabiankeil Exp $";
+const char cgi_rcs[] = "$Id: cgi.c,v 1.85 2007/01/05 14:19:02 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/cgi.c,v $
@@ -11,8 +11,8 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.78 2006/09/21 19:22:07 fabiankeil Exp $";
  *                Functions declared include:
  * 
  *
- * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
- *                Privoxy team. http://www.privoxy.org/
+ * Copyright   :  Written by and Copyright (C) 2001-2004, 2006
+ *                the SourceForge Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
  *                by and Copyright (C) 1997 Anonymous Coders and 
@@ -38,6 +38,38 @@ const char cgi_rcs[] = "$Id: cgi.c,v 1.78 2006/09/21 19:22:07 fabiankeil Exp $";
  *
  * Revisions   :
  *    $Log: cgi.c,v $
+ *    Revision 1.85  2007/01/05 14:19:02  fabiankeil
+ *    Handle pcrs_execute() errors in template_fill() properly.
+ *
+ *    Revision 1.84  2006/12/28 17:54:22  fabiankeil
+ *    Fixed gcc43 conversion warnings and replaced sprintf
+ *    calls with snprintf to give OpenBSD's gcc one less reason
+ *    to complain.
+ *
+ *    Revision 1.83  2006/12/17 19:35:19  fabiankeil
+ *    Escape ampersand in Privoxy menu.
+ *
+ *    Revision 1.82  2006/12/17 17:53:39  fabiankeil
+ *    Suppress the toggle link if remote toggling is disabled.
+ *
+ *    Revision 1.81  2006/12/09 13:49:16  fabiankeil
+ *    Fix configure option --disable-toggle.
+ *    Thanks to Peter Thoenen for reporting this.
+ *
+ *    Revision 1.80  2006/12/08 14:45:32  fabiankeil
+ *    Don't lose the FORCE_PREFIX in case of
+ *    connection problems. Fixes #612235.
+ *
+ *    Revision 1.79  2006/11/13 19:05:50  fabiankeil
+ *    Make pthread mutex locking more generic. Instead of
+ *    checking for OSX and OpenBSD, check for FEATURE_PTHREAD
+ *    and use mutex locking unless there is an _r function
+ *    available. Better safe than sorry.
+ *
+ *    Fixes "./configure --disable-pthread" and should result
+ *    in less threading-related problems on pthread-using platforms,
+ *    but it still doesn't fix BR#1122404.
+ *
  *    Revision 1.78  2006/09/21 19:22:07  fabiankeil
  *    Use CGI_PREFIX to check the referrer.
  *    The check for "http://config.privoxy.org/" fails
@@ -543,7 +575,7 @@ static const struct cgi_dispatcher cgi_dispatchers[] = {
    { "show-status", 
          cgi_show_status,  
 #ifdef FEATURE_CGI_EDIT_ACTIONS
-        "View & change the current configuration",
+        "View & change the current configuration",
 #else
         "View the current configuration",
 #endif
@@ -561,10 +593,12 @@ static const struct cgi_dispatcher cgi_dispatchers[] = {
          "Look up which actions apply to a URL and why",
          TRUE },
 #ifdef FEATURE_CGI_EDIT_ACTIONS
+#ifdef FEATURE_TOGGLE
    { "toggle",
          cgi_toggle, 
          "Toggle Privoxy on or off",
          FALSE },
+#endif /* def FEATURE_TOGGLE */
    { "edit-actions", /* Edit the actions list */
          cgi_edit_actions, 
          NULL, FALSE },
@@ -1049,7 +1083,7 @@ char get_char_param(const struct map *parameters,
    ch = *(lookup(parameters, param_name));
    if ((ch >= 'a') && (ch <= 'z'))
    {
-      ch = ch - 'a' + 'A';
+      ch = (char)(ch - 'a' + 'A');
    }
 
    return ch;
@@ -1181,7 +1215,7 @@ jb_err get_number_param(struct client_state *csp,
          return JB_ERR_CGI_PARAMS;
       }
 
-      ch -= '0';
+      ch = (char)(ch - '0');
 
       /* Note:
        *
@@ -1195,7 +1229,7 @@ jb_err get_number_param(struct client_state *csp,
          return JB_ERR_CGI_PARAMS;
       }
 
-      value = value * 10 + ch;
+      value = value * 10 + (unsigned)ch;
    }
 
    /* Success */
@@ -1228,7 +1262,9 @@ struct http_response *error_response(struct client_state *csp,
 {
    jb_err err;
    struct http_response *rsp;
-   struct map * exports = default_exports(csp, NULL);
+   struct map *exports = default_exports(csp, NULL);
+   char *path = NULL;
+
    if (exports == NULL)
    {
       return cgi_error_memory();
@@ -1240,9 +1276,19 @@ struct http_response *error_response(struct client_state *csp,
       return cgi_error_memory();
    }
 
-   err = map(exports, "host", 1, html_encode(csp->http->host), 0);
+   if (csp->flags & CSP_FLAG_FORCED)
+   {
+      path = strdup(FORCE_PREFIX);
+   }
+   else
+   {
+      path = strdup("");
+   }
+   err = string_append(&path, csp->http->path);
+
+   if (!err) err = map(exports, "host", 1, html_encode(csp->http->host), 0);
    if (!err) err = map(exports, "hostport", 1, html_encode(csp->http->hostport), 0);
-   if (!err) err = map(exports, "path", 1, html_encode(csp->http->path), 0);
+   if (!err) err = map(exports, "path", 1, html_encode_and_free_original(path), 0);
    if (!err) err = map(exports, "error", 1, html_encode_and_free_original(safe_strerror(sys_err)), 0);
    if (!err) err = map(exports, "protocol", 1, csp->http->ssl ? "https://" : "http://", 1); 
    if (!err)
@@ -1458,7 +1504,7 @@ jb_err cgi_error_no_template(struct client_state *csp,
    strcat(rsp->body, body_suffix);
 
    rsp->status = strdup(status);
-   if (rsp->body == NULL)
+   if (rsp->status == NULL)
    {
       return JB_ERR_MEMORY;
    }
@@ -1523,7 +1569,7 @@ jb_err cgi_error_unknown(struct client_state *csp,
    rsp->head_length = 0;
    rsp->is_static = 0;
 
-   sprintf(errnumbuf, "%d", error_to_report);
+   snprintf(errnumbuf, sizeof(errnumbuf), "%d", error_to_report);
 
    rsp->body = malloc(strlen(body_prefix) + strlen(errnumbuf) + strlen(body_suffix) + 1);
    if (rsp->body == NULL)
@@ -1535,7 +1581,7 @@ jb_err cgi_error_unknown(struct client_state *csp,
    strcat(rsp->body, body_suffix);
 
    rsp->status = strdup(status);
-   if (rsp->body == NULL)
+   if (rsp->status == NULL)
    {
       return JB_ERR_MEMORY;
    }
@@ -1766,7 +1812,7 @@ struct http_response *finish_http_response(struct http_response *rsp)
    /* 
     * Fill in the HTTP Status
     */
-   sprintf(buf, "HTTP/1.0 %s", rsp->status ? rsp->status : "200 OK");
+   snprintf(buf, sizeof(buf), "HTTP/1.0 %s", rsp->status ? rsp->status : "200 OK");
    err = enlist_first(rsp->headers, buf);
 
    /* 
@@ -1778,7 +1824,7 @@ struct http_response *finish_http_response(struct http_response *rsp)
    }
    if (!err)
    {
-      sprintf(buf, "Content-Length: %d", (int)rsp->content_length);
+      snprintf(buf, sizeof(buf), "Content-Length: %d", (int)rsp->content_length);
       err = enlist(rsp->headers, buf);
    }
 
@@ -2092,7 +2138,7 @@ jb_err template_load(struct client_state *csp, char **template_ptr,
  *                                    Caller must free().
  *          2  :  exports = map with fill in symbol -> name pairs
  *
- * Returns     :  JB_ERR_OK on success
+ * Returns     :  JB_ERR_OK on success (and for uncritical errors)
  *                JB_ERR_MEMORY on out-of-memory error
  *
  *********************************************************************/
@@ -2163,15 +2209,35 @@ jb_err template_fill(char **template_ptr, const struct map *exports)
       }
       else
       {
-         pcrs_execute(job, file_buffer, size, &tmp_out_buffer, &size);
-         free(file_buffer);
+         error = pcrs_execute(job, file_buffer, size, &tmp_out_buffer, &size);
+
          pcrs_free_job(job);
          if (NULL == tmp_out_buffer)
          {
             *template_ptr = NULL;
             return JB_ERR_MEMORY;
          }
-         file_buffer = tmp_out_buffer;
+
+         if (error < 0)
+         {
+            /* 
+             * Substitution failed, keep the original buffer,
+             * log the problem and ignore it.
+             * 
+             * The user might see some unresolved @CGI_VARIABLES@,
+             * but returning a special CGI error page seems unreasonable
+             * and could mask more important error messages.
+             */
+            free(tmp_out_buffer);
+            log_error(LOG_LEVEL_ERROR, "Failed to execute s/%s/%s/%s. %s",
+               buf, m->value, flags, pcrs_strerror(error));
+         }
+         else
+         {
+            /* Substitution succeeded, use modified buffer. */
+            free(file_buffer);
+            file_buffer = tmp_out_buffer;
+         }
       }
    }
 
@@ -2267,7 +2333,7 @@ struct map *default_exports(const struct client_state *csp, const char *caller)
    if (!err) err = map(exports, "my-hostname",   1, html_encode(csp->my_hostname ? csp->my_hostname : "unknown"), 0);
    if (!err) err = map(exports, "homepage",      1, html_encode(HOME_PAGE_URL), 0);
    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, "menu",          1, make_menu(caller, csp->config->feature_flags), 0);
    if (!err) err = map(exports, "code-status",   1, CODE_STATUS, 1);
    if (!strncmpic(csp->config->usermanual, "file://", 7) ||
        !strncmpic(csp->config->usermanual, "http", 4))
@@ -2453,14 +2519,18 @@ jb_err map_conditional(struct map *exports, const char *name, int choose_first)
  *
  * Description :  Returns an HTML-formatted menu of the available 
  *                unhidden CGIs, excluding the one given in <self>
+ *                and the toggle CGI if toggling is disabled.
  *
- * Parameters  :  self = name of CGI to leave out, can be NULL for
+ * Parameters  :
+ *          1  :  self = name of CGI to leave out, can be NULL for
  *                complete listing.
+ *          2  :  feature_flags = feature bitmap from csp->config
+ *                
  *
  * Returns     :  menu string, or NULL on out-of-memory error.
  *
  *********************************************************************/
-char *make_menu(const char *self)
+char *make_menu(const char *self, const unsigned feature_flags)
 {
    const struct cgi_dispatcher *d;
    char *result = strdup("");
@@ -2473,6 +2543,17 @@ char *make_menu(const char *self)
    /* List available unhidden CGI's and export as "other-cgis" */
    for (d = cgi_dispatchers; d->name; d++)
    {
+
+#ifdef FEATURE_TOGGLE
+      if (!(feature_flags & RUNTIME_FEATURE_CGI_TOGGLE) && !strcmp(d->name, "toggle"))
+      {
+         /*
+          * Suppress the toggle link if remote toggling is disabled.
+          */
+         continue;
+      }
+#endif /* def FEATURE_TOGGLE */
+
       if (d->description && strcmp(d->name, self))
       {
          string_append(&result, "<li><a href=\"" CGI_PREFIX);