Full support for enabling/disabling modular filters.
[privoxy.git] / cgiedit.c
index 4e4927d..4caaeaf 100644 (file)
--- a/cgiedit.c
+++ b/cgiedit.c
@@ -1,4 +1,4 @@
-const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.14 2002/03/05 00:24:51 jongfoster Exp $";
+const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.17 2002/03/16 14:26:42 jongfoster Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/cgiedit.c,v $
@@ -42,6 +42,16 @@ const char cgiedit_rcs[] = "$Id: cgiedit.c,v 1.14 2002/03/05 00:24:51 jongfoster
  *
  * Revisions   :
  *    $Log: cgiedit.c,v $
+ *    Revision 1.17  2002/03/16 14:26:42  jongfoster
+ *    First version of modular filters support - READ ONLY!
+ *    Fixing a double-free bug in the out-of-memory handling in map_radio().
+ *
+ *    Revision 1.16  2002/03/07 03:46:17  oes
+ *    Fixed compiler warnings
+ *
+ *    Revision 1.15  2002/03/06 22:54:35  jongfoster
+ *    Automated function-comment nitpicking.
+ *
  *    Revision 1.14  2002/03/05 00:24:51  jongfoster
  *    Patch to always edit the current actions file.
  *
@@ -321,7 +331,7 @@ static jb_err get_url_spec_param(struct client_state *csp,
 static jb_err map_radio(struct map * exports,
                         const char * optionname,
                         const char * values,
-                        char value);
+                        int value);
 static jb_err actions_to_radio(struct map * exports,
                                const struct action_spec *action);
 static jb_err actions_from_radio(const struct map * parameters,
@@ -768,7 +778,7 @@ jb_err edit_write_file(struct editable_file * file)
 
                /* Allocate new memory for string */
                len = strlen(cur_line->unprocessed);
-               if (NULL == (str = malloc(len + 1 + numhash)))
+               if (NULL == (str = malloc((size_t) len + 1 + numhash)))
                {
                   /* Uh oh, just trashed file! */
                   fclose(fp);
@@ -955,7 +965,7 @@ static void edit_free_file_lines(struct file_line * first_line)
  *********************************************************************/
 static int match_actions_file_header_line(const char * line, const char * name)
 {
-   int len;
+   size_t len;
 
    assert(line);
    assert(name);
@@ -1021,7 +1031,7 @@ static jb_err split_line_on_equals(const char * line, char ** pname, char ** pva
 {
    const char * name_end;
    const char * value_start;
-   int name_len;
+   size_t name_len;
 
    assert(line);
    assert(pname);
@@ -1101,7 +1111,7 @@ static jb_err split_line_on_equals(const char * line, char ** pname, char ** pva
 jb_err edit_parse_actions_file(struct editable_file * file)
 {
    struct file_line * cur_line;
-   int len;
+   size_t len;
    const char * text; /* Text from a line */
    char * name;  /* For lines of the form name=value */
    char * value; /* For lines of the form name=value */
@@ -1867,7 +1877,7 @@ static jb_err get_number_param(struct client_state *csp,
    assert(name);
    assert(pvalue);
 
-   *pvalue = -1;
+   *pvalue = 0; 
 
    param = lookup(parameters, name);
    if (!*param)
@@ -1906,6 +1916,7 @@ static jb_err get_number_param(struct client_state *csp,
    *pvalue = value;
 
    return JB_ERR_OK;
+
 }
 
 
@@ -2065,9 +2076,9 @@ static jb_err get_url_spec_param(struct client_state *csp,
 static jb_err map_radio(struct map * exports,
                         const char * optionname,
                         const char * values,
-                        char value)
+                        int value)
 {
-   int len;
+   size_t len;
    char * buf;
    char * p;
    char c;
@@ -2095,20 +2106,13 @@ static jb_err map_radio(struct map * exports,
          *p = c;
          if (map(exports, buf, 1, "", 1))
          {
-            free(buf);
             return JB_ERR_MEMORY;
          }
       }
    }
 
    *p = value;
-   if (map(exports, buf, 0, "checked", 1))
-   {
-      free(buf);
-      return JB_ERR_MEMORY;
-   }
-
-   return JB_ERR_OK;
+   return map(exports, buf, 0, "checked", 1);
 }
 
 
@@ -2721,6 +2725,8 @@ jb_err cgi_edit_actions_for_url(struct client_state *csp,
    struct file_line * cur_line;
    unsigned line_number;
    jb_err err;
+   struct file_list *filter_file;
+   struct re_filterfile_spec *filter_group;
 
    if (0 == (csp->config->feature_flags & RUNTIME_FEATURE_CGI_EDIT_ACTIONS))
    {
@@ -2769,6 +2775,117 @@ jb_err cgi_edit_actions_for_url(struct client_state *csp,
 
    if (!err) err = actions_to_radio(exports, cur_line->data.action);
 
+   filter_file = csp->rlist;
+   filter_group = ((filter_file != NULL) ? filter_file->f : NULL);
+
+   if (!err) err = map_conditional(exports, "any-filters-defined", (filter_group != NULL));
+
+   if (err)
+   {
+      edit_free_file(file);
+      free_map(exports);
+      return err;
+   }
+
+   if (filter_group == NULL)
+   {
+      err = map(exports, "filter-params", 1, "", 1);
+   }
+   else
+   {
+      /* We have some entries in the filter list */
+      char * result;
+      int index = 0;
+      char * filter_template;
+
+      err = template_load(csp, &filter_template, "edit-actions-for-url-filter");
+      if (err)
+      {
+         edit_free_file(file);
+         free_map(exports);
+         if (err == JB_ERR_FILE)
+         {
+            return cgi_error_no_template(csp, rsp, "edit-actions-for-url-filter");
+         }
+         return err;
+      }
+
+      result = strdup("");
+
+      for (;(!err) && (filter_group != NULL); filter_group = filter_group->next)
+      {
+         char current_mode = 'x';
+         struct list_entry *filter_name;
+         char * this_line;
+         struct map *line_exports;
+         char number[20];
+
+         filter_name = cur_line->data.action->multi_add[ACTION_MULTI_FILTER]->first;
+         while ((filter_name != NULL)
+             && (0 != strcmp(filter_group->filtername, filter_name->str)))
+         {
+              filter_name = filter_name->next;
+         }
+
+         if (filter_name != NULL)
+         {
+            current_mode = 'y';
+         }
+         else
+         {
+            filter_name = cur_line->data.action->multi_remove[ACTION_MULTI_FILTER]->first;
+            while ((filter_name != NULL)
+                && (0 != strcmp(filter_group->filtername, filter_name->str)))
+            {
+                 filter_name = filter_name->next;
+            }
+            if (filter_name != NULL)
+            {
+               current_mode = 'n';
+            }
+         }
+
+         /* Generate a unique serial number */
+         snprintf(number, sizeof(number), "%x", index++);
+         number[sizeof(number) - 1] = '\0';
+
+         line_exports = new_map();
+         if (line_exports == NULL)
+         {
+            err = JB_ERR_MEMORY;
+            freez(result);
+         }
+         else
+         {
+            if (!err) err = map(line_exports, "index", 1, number, 1);
+            if (!err) err = map(line_exports, "name",  1, filter_group->filtername, 1);
+            if (!err) err = map_radio(line_exports, "this-filter", "ynx", current_mode);
+
+            this_line = NULL;
+            if (!err)
+            {
+               this_line = strdup(filter_template);
+               if (this_line == NULL) err = JB_ERR_MEMORY;
+            }
+            if (!err) err = template_fill(&this_line, line_exports);
+            string_join(&result, this_line);
+
+            free_map(line_exports);
+         }
+      }
+      if (!err)
+      {
+         err = map(exports, "filter-params", 1, result, 0);
+      }
+      else
+      {
+         freez(result);
+      }
+   }
+
+   if (!err) err = map_radio(exports, "filter-all", "nx",
+      (cur_line->data.action->multi_remove_all[ACTION_MULTI_FILTER] ? 'n' : 'x'));
+
    edit_free_file(file);
 
    if (err)
@@ -2807,12 +2924,14 @@ jb_err cgi_edit_actions_submit(struct client_state *csp,
    unsigned sectionid;
    char * actiontext;
    char * newtext;
-   int len;
+   size_t len;
    struct editable_file * file;
    struct file_line * cur_line;
    unsigned line_number;
    char * target;
    jb_err err;
+   int index;
+   char ch;
 
    if (0 == (csp->config->feature_flags & RUNTIME_FEATURE_CGI_EDIT_ACTIONS))
    {
@@ -2857,6 +2976,70 @@ jb_err cgi_edit_actions_submit(struct client_state *csp,
       return err;
    }
 
+   ch = ijb_toupper((int)lookup(parameters, "filter_all")[0]);
+   if (ch == 'N')
+   {
+      list_remove_all(cur_line->data.action->multi_add[ACTION_MULTI_FILTER]);
+      list_remove_all(cur_line->data.action->multi_remove[ACTION_MULTI_FILTER]);
+      cur_line->data.action->multi_remove_all[ACTION_MULTI_FILTER] = 1;
+   }
+   else if (ch == 'X')
+   {
+      cur_line->data.action->multi_remove_all[ACTION_MULTI_FILTER] = 0;
+   }
+
+   for (index = 0; ; index++)
+   {
+      char key_value[30];
+      char key_name[30];
+      const char *name;
+      char value;
+
+      /* Generate the keys */
+      snprintf(key_value, sizeof(key_value), "filter_r%x", index);
+      key_value[sizeof(key_value) - 1] = '\0';
+      snprintf(key_name, sizeof(key_name), "filter_n%x", index);
+      key_name[sizeof(key_name) - 1] = '\0';
+
+      name = lookup(parameters, key_name);
+
+      if (*name == '\0')
+      {
+         /* End of list */
+         break;
+      }
+
+
+      value = ijb_toupper((int)lookup(parameters, key_value)[0]);
+      if (value == 'Y')
+      {
+         list_remove_item(cur_line->data.action->multi_add[ACTION_MULTI_FILTER], name);
+         if (!err) err = enlist(cur_line->data.action->multi_add[ACTION_MULTI_FILTER], name);
+         list_remove_item(cur_line->data.action->multi_remove[ACTION_MULTI_FILTER], name);
+      }
+      else if (value == 'N')
+      {
+         list_remove_item(cur_line->data.action->multi_add[ACTION_MULTI_FILTER], name);
+         if (!cur_line->data.action->multi_remove_all[ACTION_MULTI_FILTER])
+         {
+            list_remove_item(cur_line->data.action->multi_remove[ACTION_MULTI_FILTER], name);
+            if (!err) err = enlist(cur_line->data.action->multi_remove[ACTION_MULTI_FILTER], name);
+         }
+      }
+      else if (value == 'X')
+      {
+         list_remove_item(cur_line->data.action->multi_add[ACTION_MULTI_FILTER], name);
+         list_remove_item(cur_line->data.action->multi_remove[ACTION_MULTI_FILTER], name);
+      }
+   }
+
+   if(err)
+   {
+      /* Out of memory */
+      edit_free_file(file);
+      return err;
+   }
+
    if (NULL == (actiontext = actions_to_text(cur_line->data.action)))
    {
       /* Out of memory */
@@ -3882,6 +4065,44 @@ jb_err cgi_toggle(struct client_state *csp,
 }
 
 
+/*********************************************************************
+ *
+ * Function    :  javascriptify
+ *
+ * Description :  Converts a string into a form JavaScript will like.
+ *
+ *                Netscape 4's JavaScript sucks - it doesn't use 
+ *                "id" parameters, so you have to set the "name"
+ *                used to submit a form element to something JavaScript
+ *                will like.  (Or access the elements by index in an
+ *                array.  That array contains >60 elements and will
+ *                be changed whenever we add a new action to the
+ *                editor, so I'm NOT going to use indexes that have
+ *                to be figured out by hand.)
+ *
+ *                Currently the only thing we have to worry about
+ *                is "-" ==> "_" conversion.
+ *
+ *                This is a length-preserving operation so it is
+ *                carried out in-place, no memory is allocated
+ *                or freed.
+ *
+ * Parameters  :
+ *          1  :  identifier = String to make JavaScript-friendly.
+ *
+ * Returns     :  N/A
+ *
+ *********************************************************************/
+static void javascriptify(char * identifier)
+{
+   char * p = identifier;
+   while (NULL != (p = strchr(p, '-')))
+   {
+      *p++ = '_';
+   }
+}
+
+
 /*********************************************************************
  *
  * Function    :  actions_to_radio
@@ -4011,44 +4232,6 @@ static jb_err actions_to_radio(struct map * exports,
 }
 
 
-/*********************************************************************
- *
- * Function    :  javascriptify
- *
- * Description :  Converts a string into a form JavaScript will like.
- *
- *                Netscape 4's JavaScript sucks - it doesn't use 
- *                "id" parameters, so you have to set the "name"
- *                used to submit a form element to something JavaScript
- *                will like.  (Or access the elements by index in an
- *                array.  That array contains >60 elements and will
- *                be changed whenever we add a new action to the
- *                editor, so I'm NOT going to use indexes that have
- *                to be figured out by hand.)
- *
- *                Currently the only thing we have to worry about
- *                is "-" ==> "_" conversion.
- *
- *                This is a length-preserving operation so it is
- *                carried out in-place, no memory is allocated
- *                or freed.
- *
- * Parameters  :
- *          1  :  identifier = String to make JavaScript-friendly.
- *
- * Returns     :  N/A
- *
- *********************************************************************/
-static void javascriptify(char * identifier)
-{
-   char * p = identifier;
-   while (NULL != (p = strchr(p, '-')))
-   {
-      *p++ = '_';
-   }
-}
-
-
 /*********************************************************************
  *
  * Function    :  actions_from_radio
@@ -4067,7 +4250,7 @@ static void javascriptify(char * identifier)
  *
  *********************************************************************/
 static jb_err actions_from_radio(const struct map * parameters,
-                              struct action_spec *action)
+                                 struct action_spec *action)
 {
    static int first_time = 1;
    const char * param;