From 77cad8561cec1699d7a4317e34c5590d566c9eb8 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Sat, 8 Apr 2017 21:24:45 -0700 Subject: Move the filter file reading code to libui. It doesn't belong in libwireshark, as it doesn't affect dissection, but it *does* belong in libui, as it's helper code for the UIs. Change-Id: I8a5e0640a299a08e9ec1917dd253197438ebfdbc Reviewed-on: https://code.wireshark.org/review/20974 Reviewed-by: Guy Harris --- filter_files.c | 662 --------------------------------------------------------- 1 file changed, 662 deletions(-) delete mode 100644 filter_files.c (limited to 'filter_files.c') diff --git a/filter_files.c b/filter_files.c deleted file mode 100644 index c5e8818194..0000000000 --- a/filter_files.c +++ /dev/null @@ -1,662 +0,0 @@ -/* filters.c - * Code for reading and writing the filters file. - * - * Wireshark - Network traffic analyzer - * By Gerald Combs - * Copyright 1998 Gerald Combs - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -#include -#include -#include - -#include - -#include -#include -#include - -#include "filter_files.h" - -/* - * Old filter file name. - */ -#define FILTER_FILE_NAME "filters" - -/* - * Capture filter file name. - */ -#define CFILTER_FILE_NAME "cfilters" - -/* - * Display filter file name. - */ -#define DFILTER_FILE_NAME "dfilters" - -/* - * List of capture filters - saved. - */ -static GList *capture_filters = NULL; - -/* - * List of display filters - saved. - */ -static GList *display_filters = NULL; - -/* - * List of capture filters - currently edited. - */ -static GList *capture_edited_filters = NULL; - -/* - * List of display filters - currently edited. - */ -static GList *display_edited_filters = NULL; - -/* - * Read in a list of filters. - * - * On success, "*pref_path_return" is set to NULL. - * On error, "*pref_path_return" is set to point to the pathname of - * the file we tried to read - it should be freed by our caller - - * and "*errno_return" is set to the error. - */ - -#define INIT_BUF_SIZE 128 - -static GList * -add_filter_entry(GList *fl, const char *filt_name, const char *filt_expr) -{ - filter_def *filt; - - filt = (filter_def *) g_malloc(sizeof(filter_def)); - filt->name = g_strdup(filt_name); - filt->strval = g_strdup(filt_expr); - return g_list_append(fl, filt); -} - -static void -free_filter_entry(gpointer data) -{ - filter_def *filt = (filter_def*)data; - g_free(filt->name); - g_free(filt->strval); - g_free(filt); -} - -void free_filter_lists(void) -{ - if (capture_filters) { - g_list_free_full(capture_filters, free_filter_entry); - capture_filters = NULL; - } - if (display_filters) { - g_list_free_full(display_filters, free_filter_entry); - display_filters = NULL; - } - if (capture_edited_filters) { - g_list_free_full(capture_edited_filters, free_filter_entry); - capture_edited_filters = NULL; - } - if (display_edited_filters) { - g_list_free_full(display_edited_filters, free_filter_entry); - display_edited_filters = NULL; - } -} - -static GList * -remove_filter_entry(GList *fl, GList *fl_entry) -{ - filter_def *filt; - - filt = (filter_def *) fl_entry->data; - g_free(filt->name); - g_free(filt->strval); - g_free(filt); - return g_list_remove_link(fl, fl_entry); -} - -static int -skip_whitespace(FILE *ff) -{ - int c; - - while ((c = getc(ff)) != EOF && c != '\n' && g_ascii_isspace(c)) - ; - return c; -} - -static int -getc_crlf(FILE *ff) -{ - int c; - - c = getc(ff); - if (c == '\r') { - /* Treat CR-LF at the end of a line like LF, so that if we're reading - * a Windows-format file on UN*X, we handle it the same way we'd handle - * a UN*X-format file. */ - c = getc(ff); - if (c != EOF && c != '\n') { - /* Put back the character after the CR, and process the CR normally. */ - ungetc(c, ff); - c = '\r'; - } - } - return c; -} - -void -read_filter_list(filter_list_type_t list_type, char **pref_path_return, - int *errno_return) -{ - const char *ff_name; - char *ff_path; - FILE *ff; - GList **flpp; - int c; - char *filt_name, *filt_expr; - int filt_name_len, filt_expr_len; - int filt_name_index, filt_expr_index; - int line = 1; - - *pref_path_return = NULL; /* assume no error */ - - switch (list_type) { - - case CFILTER_LIST: - ff_name = CFILTER_FILE_NAME; - flpp = &capture_filters; - break; - - case DFILTER_LIST: - ff_name = DFILTER_FILE_NAME; - flpp = &display_filters; - break; - - default: - g_assert_not_reached(); - return; - } - - /* try to open personal "cfilters"/"dfilters" file */ - ff_path = get_persconffile_path(ff_name, TRUE); - if ((ff = ws_fopen(ff_path, "r")) == NULL) { - /* - * Did that fail because the file didn't exist? - */ - if (errno != ENOENT) { - /* - * No. Just give up. - */ - *pref_path_return = ff_path; - *errno_return = errno; - return; - } - - /* - * Yes. See if there's an "old style" personal "filters" file; if so, read it. - * This means that a user will start out with their capture and - * display filter lists being identical; each list may contain - * filters that don't belong in that list. The user can edit - * the filter lists, and delete the ones that don't belong in - * a particular list. - */ - g_free(ff_path); - ff_path = get_persconffile_path(FILTER_FILE_NAME, FALSE); - if ((ff = ws_fopen(ff_path, "r")) == NULL) { - /* - * Did that fail because the file didn't exist? - */ - if (errno != ENOENT) { - /* - * No. Just give up. - */ - *pref_path_return = ff_path; - *errno_return = errno; - return; - } - - /* - * Try to open the global "cfilters/dfilters" file */ - g_free(ff_path); - ff_path = get_datafile_path(ff_name); - if ((ff = ws_fopen(ff_path, "r")) == NULL) { - - /* - * Well, that didn't work, either. Just give up. - * Return an error if the file existed but we couldn't open it. - */ - if (errno != ENOENT) { - *pref_path_return = ff_path; - *errno_return = errno; - } else { - g_free(ff_path); - } - return; - } - } - } - - /* If we already have a list of filters, discard it. */ - /* this should never happen - this function is called only once for each list! */ - while(*flpp) { - *flpp = remove_filter_entry(*flpp, g_list_first(*flpp)); - } - - /* Allocate the filter name buffer. */ - filt_name_len = INIT_BUF_SIZE; - filt_name = (char *)g_malloc(filt_name_len + 1); - filt_expr_len = INIT_BUF_SIZE; - filt_expr = (char *)g_malloc(filt_expr_len + 1); - - for (line = 1; ; line++) { - /* Lines in a filter file are of the form - - "name" expression - - where "name" is a name, in quotes - backslashes in the name - escape the next character, so quotes and backslashes can appear - in the name - and "expression" is a filter expression, not in - quotes, running to the end of the line. */ - - /* Skip over leading white space, if any. */ - c = skip_whitespace(ff); - - if (c == EOF) - break; /* Nothing more to read */ - if (c == '\n') - continue; /* Blank line. */ - - /* "c" is the first non-white-space character. - If it's not a quote, it's an error. */ - if (c != '"') { - g_warning("'%s' line %d doesn't have a quoted filter name.", ff_path, - line); - while (c != '\n') - c = getc(ff); /* skip to the end of the line */ - continue; - } - - /* Get the name of the filter. */ - filt_name_index = 0; - for (;;) { - c = getc_crlf(ff); - if (c == EOF || c == '\n') - break; /* End of line - or end of file */ - if (c == '"') { - /* Closing quote. */ - if (filt_name_index >= filt_name_len) { - /* Filter name buffer isn't long enough; double its length. */ - filt_name_len *= 2; - filt_name = (char *)g_realloc(filt_name, filt_name_len + 1); - } - filt_name[filt_name_index] = '\0'; - break; - } - if (c == '\\') { - /* Next character is escaped */ - c = getc_crlf(ff); - if (c == EOF || c == '\n') - break; /* End of line - or end of file */ - } - /* Add this character to the filter name string. */ - if (filt_name_index >= filt_name_len) { - /* Filter name buffer isn't long enough; double its length. */ - filt_name_len *= 2; - filt_name = (char *)g_realloc(filt_name, filt_name_len + 1); - } - filt_name[filt_name_index] = c; - filt_name_index++; - } - - if (c == EOF) { - if (!ferror(ff)) { - /* EOF, not error; no newline seen before EOF */ - g_warning("'%s' line %d doesn't have a newline.", ff_path, - line); - } - break; /* nothing more to read */ - } - - if (c != '"') { - /* No newline seen before end-of-line */ - g_warning("'%s' line %d doesn't have a closing quote.", ff_path, - line); - continue; - } - - /* Skip over separating white space, if any. */ - c = skip_whitespace(ff); - - if (c == EOF) { - if (!ferror(ff)) { - /* EOF, not error; no newline seen before EOF */ - g_warning("'%s' line %d doesn't have a newline.", ff_path, - line); - } - break; /* nothing more to read */ - } - - if (c == '\n') { - /* No filter expression */ - g_warning("'%s' line %d doesn't have a filter expression.", ff_path, - line); - continue; - } - - /* "c" is the first non-white-space character; it's the first - character of the filter expression. */ - filt_expr_index = 0; - for (;;) { - /* Add this character to the filter expression string. */ - if (filt_expr_index >= filt_expr_len) { - /* Filter expressioin buffer isn't long enough; double its length. */ - filt_expr_len *= 2; - filt_expr = (char *)g_realloc(filt_expr, filt_expr_len + 1); - } - filt_expr[filt_expr_index] = c; - filt_expr_index++; - - /* Get the next character. */ - c = getc_crlf(ff); - if (c == EOF || c == '\n') - break; - } - - if (c == EOF) { - if (!ferror(ff)) { - /* EOF, not error; no newline seen before EOF */ - g_warning("'%s' line %d doesn't have a newline.", ff_path, - line); - } - break; /* nothing more to read */ - } - - /* We saw the ending newline; terminate the filter expression string */ - if (filt_expr_index >= filt_expr_len) { - /* Filter expressioin buffer isn't long enough; double its length. */ - filt_expr_len *= 2; - filt_expr = (char *)g_realloc(filt_expr, filt_expr_len + 1); - } - filt_expr[filt_expr_index] = '\0'; - - /* Add the new filter to the list of filters */ - *flpp = add_filter_entry(*flpp, filt_name, filt_expr); - } - if (ferror(ff)) { - *pref_path_return = ff_path; - *errno_return = errno; - } else - g_free(ff_path); - fclose(ff); - g_free(filt_name); - g_free(filt_expr); - - /* init the corresponding edited list */ - switch (list_type) { - case CFILTER_LIST: - copy_filter_list(CFILTER_EDITED_LIST, CFILTER_LIST); - break; - case DFILTER_LIST: - copy_filter_list(DFILTER_EDITED_LIST, DFILTER_LIST); - break; - default: - g_assert_not_reached(); - return; - } -} - -/* - * Get a pointer to a list of filters. - */ -static GList ** -get_filter_list(filter_list_type_t list_type) -{ - GList **flpp; - - switch (list_type) { - - case CFILTER_LIST: - flpp = &capture_filters; - break; - - case DFILTER_LIST: - flpp = &display_filters; - break; - - case CFILTER_EDITED_LIST: - flpp = &capture_edited_filters; - break; - - case DFILTER_EDITED_LIST: - flpp = &display_edited_filters; - break; - - default: - g_assert_not_reached(); - flpp = NULL; - } - return flpp; -} - -/* - * Get a pointer to the first entry in a filter list. - */ -GList * -get_filter_list_first(filter_list_type_t list_type) -{ - GList **flpp; - - flpp = get_filter_list(list_type); - return g_list_first(*flpp); -} - -/* - * Add a new filter to the end of a list. - * Returns a pointer to the newly-added entry. - */ -GList * -add_to_filter_list(filter_list_type_t list_type, const char *name, - const char *expression) -{ - GList **flpp; - - flpp = get_filter_list(list_type); - *flpp = add_filter_entry(*flpp, name, expression); - - return g_list_last(*flpp); -} - -/* - * Remove a filter from a list. - */ -void -remove_from_filter_list(filter_list_type_t list_type, GList *fl_entry) -{ - GList **flpp; - - flpp = get_filter_list(list_type); - *flpp = remove_filter_entry(*flpp, fl_entry); -} - -/* - * Write out a list of filters. - * - * On success, "*pref_path_return" is set to NULL. - * On error, "*pref_path_return" is set to point to the pathname of - * the file we tried to read - it should be freed by our caller - - * and "*errno_return" is set to the error. - */ -void -save_filter_list(filter_list_type_t list_type, char **pref_path_return, - int *errno_return) -{ - const gchar *ff_name; - gchar *ff_path, *ff_path_new; - GList *fl; - GList *flpp; - filter_def *filt; - FILE *ff; - guchar *p, c; - - *pref_path_return = NULL; /* assume no error */ - - switch (list_type) { - - case CFILTER_LIST: - ff_name = CFILTER_FILE_NAME; - fl = capture_filters; - break; - - case DFILTER_LIST: - ff_name = DFILTER_FILE_NAME; - fl = display_filters; - break; - - default: - g_assert_not_reached(); - return; - } - - ff_path = get_persconffile_path(ff_name, TRUE); - - /* Write to "XXX.new", and rename if that succeeds. - That means we don't trash the file if we fail to write it out - completely. */ - ff_path_new = g_strdup_printf("%s.new", ff_path); - - if ((ff = ws_fopen(ff_path_new, "w")) == NULL) { - *pref_path_return = ff_path; - *errno_return = errno; - g_free(ff_path_new); - return; - } - flpp = g_list_first(fl); - while (flpp) { - filt = (filter_def *) flpp->data; - - /* Write out the filter name as a quoted string; escape any quotes - or backslashes. */ - putc('"', ff); - for (p = (guchar *)filt->name; (c = *p) != '\0'; p++) { - if (c == '"' || c == '\\') - putc('\\', ff); - putc(c, ff); - } - putc('"', ff); - - /* Separate the filter name and value with a space. */ - putc(' ', ff); - - /* Write out the filter expression and a newline. */ - fprintf(ff, "%s\n", filt->strval); - if (ferror(ff)) { - *pref_path_return = ff_path; - *errno_return = errno; - fclose(ff); - ws_unlink(ff_path_new); - g_free(ff_path_new); - return; - } - flpp = flpp->next; - } - if (fclose(ff) == EOF) { - *pref_path_return = ff_path; - *errno_return = errno; - ws_unlink(ff_path_new); - g_free(ff_path_new); - return; - } - -#ifdef _WIN32 - /* ANSI C doesn't say whether "rename()" removes the target if it - exists; the Win32 call to rename files doesn't do so, which I - infer is the reason why the MSVC++ "rename()" doesn't do so. - We must therefore remove the target file first, on Windows. - - XXX - ws_rename() should be ws_stdio_rename() on Windows, - and ws_stdio_rename() uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING, - so it should remove the target if it exists, so this stuff - shouldn't be necessary. Perhaps it dates back to when we were - calling rename(), with that being a wrapper around Microsoft's - _rename(), which didn't remove the target. */ - if (ws_remove(ff_path) < 0 && errno != ENOENT) { - /* It failed for some reason other than "it's not there"; if - it's not there, we don't need to remove it, so we just - drive on. */ - *pref_path_return = ff_path; - *errno_return = errno; - ws_unlink(ff_path_new); - g_free(ff_path_new); - return; - } -#endif - - if (ws_rename(ff_path_new, ff_path) < 0) { - *pref_path_return = ff_path; - *errno_return = errno; - ws_unlink(ff_path_new); - g_free(ff_path_new); - return; - } - g_free(ff_path_new); - g_free(ff_path); -} - -/* - * Copy a filter list into another. - */ -void copy_filter_list(filter_list_type_t dest_type, filter_list_type_t src_type) -{ - GList **flpp_dest; - GList **flpp_src; - GList *flp_src; - filter_def *filt; - - g_assert(dest_type != src_type); - - flpp_dest = get_filter_list(dest_type); - flpp_src = get_filter_list(src_type); - /* throw away the "old" destination list - a NULL list is ok here */ - while(*flpp_dest) { - *flpp_dest = remove_filter_entry(*flpp_dest, g_list_first(*flpp_dest)); - } - g_assert(g_list_length(*flpp_dest) == 0); - - /* copy the list entries */ - for(flp_src = g_list_first(*flpp_src); flp_src; flp_src = g_list_next(flp_src)) { - filt = (filter_def *)(flp_src->data); - - *flpp_dest = add_filter_entry(*flpp_dest, filt->name, filt->strval); - } -} - -/* - * Editor modelines - http://www.wireshark.org/tools/modelines.html - * - * Local Variables: - * c-basic-offset: 2 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * ex: set shiftwidth=2 tabstop=8 expandtab: - * :indentSize=2:tabSize=8:noTabs=true: - */ -- cgit v1.2.3