+ /*
+ * XXX: Some browsers (at least IE6 and IE7) have an artifical URL
+ * length limitation and ignore clicks on the Submit buttons if
+ * the resulting GET URL would be longer than their limit.
+ *
+ * In Privoxy 3.0.5 beta the standard edit-actions-for-url template
+ * reached this limit and action editing stopped working in these
+ * browsers (BR #1570678).
+ *
+ * The config option split-large-forms works around this browser
+ * bug (HTTP has no URL lenght limitation) by deviding the action
+ * list form into multiple smaller ones. It means the URLs are shorter
+ * and work in broken browsers as well, but the user can no longer change
+ * all actions with one submit.
+ *
+ * A better solution would be to switch to POST requests,
+ * but this will do for now.
+ */
+ if(!err && (csp->config->feature_flags & RUNTIME_FEATURE_SPLIT_LARGE_FORMS))
+ {
+ /* Generate multiple smaller form by killing the big one. */
+ err = map_block_killer(exports, "one-form-only");
+ }
+ else
+ {
+ /* Default: Generate one large form by killing the smaller ones. */
+ err = map_block_killer(exports, "multiple-forms");
+ }
+
+ for (i = 0; i < MAX_AF_FILES; i++)
+ {
+ if ((csp->rlist[i] != NULL) && (csp->rlist[i]->f != NULL))
+ {
+ if (!err) err = map_conditional(exports, "any-filters-defined", 1);
+ have_filters = 1;
+ break;
+ }
+ }
+
+ if (err)
+ {
+ edit_free_file(file);
+ free_map(exports);
+ return err;
+ }
+
+ if (0 == have_filters)
+ {
+ err = map(exports, "filter-params", 1, "", 1);
+ }
+ else
+ {
+ /*
+ * List available filters and their settings.
+ */
+ char *content_filter_params;
+ char *server_header_filter_params;
+ char *client_header_filter_params;
+ char *filter_template;
+ int filter_identifier = 0;
+
+ err = template_load(csp, &filter_template, "edit-actions-for-url-filter", 0);
+ 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;
+ }
+
+ err = template_fill(&filter_template, exports);
+
+ content_filter_params = strdup("");
+ server_header_filter_params = strdup("");
+ client_header_filter_params = strdup("");
+
+ for (i = 0; i < MAX_AF_FILES; i++)
+ {
+ if ((csp->rlist[i] != NULL) && (csp->rlist[i]->f != NULL))
+ {
+ filter_group = csp->rlist[i]->f;
+ for (;(!err) && (filter_group != NULL); filter_group = filter_group->next)
+ {
+ char current_mode = 'x';
+ char number[20];
+ int multi_action_index = 0;
+ struct list_entry *filter_name;
+ struct map *line_exports;
+ char *this_line;
+ char *filter_type;
+ char *abbr_filter_type;
+ char *anchor;
+ char **current_params;
+
+ switch (filter_group->type)
+ {
+ case FT_CONTENT_FILTER:
+ /* XXX: Should we call it content-filter instead? */
+ filter_type = "filter";
+ abbr_filter_type = "F";
+ multi_action_index = ACTION_MULTI_FILTER;
+ anchor = "FILTER";
+ current_params = &content_filter_params;
+ break;
+ case FT_SERVER_HEADER_FILTER:
+ filter_type = "server-header-filter";
+ abbr_filter_type = "S";
+ multi_action_index = ACTION_MULTI_SERVER_HEADER_FILTER;
+ current_params = &server_header_filter_params;
+ anchor = "SERVER-HEADER-FILTER"; /* XXX: no documentation available yet */
+ break;
+ case FT_CLIENT_HEADER_FILTER:
+ filter_type = "client-header-filter";
+ abbr_filter_type = "C";
+ multi_action_index = ACTION_MULTI_CLIENT_HEADER_FILTER;
+ current_params = &client_header_filter_params;
+ anchor = "CLIENT-HEADER-FILTER"; /* XXX: no documentation available yet */
+ break;
+ default:
+ log_error(LOG_LEVEL_FATAL,
+ "cgi_edit_actions_for_url: Unknown filter type: %u for filter %s.",
+ filter_group->type, filter_group->name);
+ /* Not reached. */
+ }
+ assert(multi_action_index);
+
+ filter_name = cur_line->data.action->multi_add[multi_action_index]->first;
+ while ((filter_name != NULL)
+ && (0 != strcmp(filter_group->name, filter_name->str)))
+ {
+ filter_name = filter_name->next;
+ }
+
+ if (filter_name != NULL)
+ {
+ current_mode = 'y';
+ }
+ else
+ {
+ filter_name = cur_line->data.action->multi_remove[multi_action_index]->first;
+ while ((filter_name != NULL)
+ && (0 != strcmp(filter_group->name, 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", filter_identifier++);
+ number[sizeof(number) - 1] = '\0';
+
+ line_exports = new_map();
+ if (line_exports == NULL)
+ {
+ err = JB_ERR_MEMORY;
+ freez(*current_params); /* XXX: really necessary? */
+ }
+ else
+ {
+ if (!err) err = map(line_exports, "index", 1, number, 1);
+ if (!err) err = map(line_exports, "name", 1, filter_group->name, 1);
+ if (!err) err = map(line_exports, "description", 1, filter_group->description, 1);
+ if (!err) err = map_radio(line_exports, "this-filter", "ynx", current_mode);
+ if (!err) err = map(line_exports, "filter-type", 1, filter_type, 1);
+ if (!err) err = map(line_exports, "abbr-filter-type", 1, abbr_filter_type, 1);
+ if (!err) err = map(line_exports, "anchor", 1, anchor, 1);
+
+ 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(current_params, this_line);
+
+ free_map(line_exports);
+ }
+ }
+ }
+ }
+ freez(filter_template);
+
+ if (!err) err = map(exports, "content-filter-params", 1, content_filter_params, 0);
+ if (!err) err = map(exports, "server-header-filter-params", 1, server_header_filter_params, 0);
+ if (!err) err = map(exports, "client-header-filter-params", 1, client_header_filter_params, 0);
+ if (err)
+ {
+ freez(content_filter_params);
+ freez(server_header_filter_params);
+ freez(client_header_filter_params);
+ }
+ }
+
+ if (!err) err = map_radio(exports, "filter-all", "nx",
+ (cur_line->data.action->multi_remove_all[ACTION_MULTI_FILTER] ? 'n' : 'x'));
+