From aab5ad074e88e3c03e438b2b9ff503191c6f6458 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Fri, 6 Jul 2018 02:06:56 -0700 Subject: [PATCH] Fix the calculation of a file's "basename". Strip off only extensions that correspond to file types we know about; QFileInfo::baseName() strips off *all* extensions, where "extension" is "anything preceded by a .", so it turns foo.bar.pcap.gz into foo, not foo.bar. We don't want that; instead, we strip off only those extensions that correspond to file types we know how to read, so we'd strip off .pcap.gz in foo.bar.pcap.gz, and strip off .pcap in foo.bar.pcap, leaving foo.bar in both cases. Change-Id: I5385921ad2f0fef815d52e9902fef15735fd9dae Reviewed-on: https://code.wireshark.org/review/28636 Reviewed-by: Guy Harris --- debian/libwiretap0.symbols | 1 + file.c | 46 ++++++++++++++++++++++++++++++++++++++ file.h | 11 +++++++++ ui/qt/capture_file.cpp | 11 +++++---- wiretap/file_access.c | 43 +++++++++++++++++++++++++++++------ wiretap/wtap.h | 2 ++ 6 files changed, 101 insertions(+), 13 deletions(-) diff --git a/debian/libwiretap0.symbols b/debian/libwiretap0.symbols index 400458cfb2..0f7e397ab0 100644 --- a/debian/libwiretap0.symbols +++ b/debian/libwiretap0.symbols @@ -97,6 +97,7 @@ libwiretap.so.0 libwiretap0 #MINVER# wtap_free_idb_info@Base 1.99.9 wtap_fstat@Base 1.9.1 wtap_get_all_capture_file_extensions_list@Base 2.3.0 + wtap_get_all_file_extensions_list@Base 2.6.2 wtap_get_buf_ptr@Base 2.5.1 wtap_get_bytes_dumped@Base 1.9.1 wtap_get_debug_if_descr@Base 1.99.9 diff --git a/file.c b/file.c index 6d95766040..a94ecd5eff 100644 --- a/file.c +++ b/file.c @@ -1023,6 +1023,52 @@ cf_get_display_name(capture_file *cf) return displayname; } +gchar * +cf_get_basename(capture_file *cf) +{ + gchar *displayname; + + /* Return a name to use in the GUI for the basename for files to + which we save statistics */ + if (!cf->is_tempfile) { + /* Get the last component of the file name, and use that. */ + if (cf->filename) { + displayname = g_filename_display_basename(cf->filename); + + /* If the file name ends with any extension that corresponds + to a file type we support - including compressed versions + of those files - strip it off. */ + size_t displayname_len = strlen(displayname); + GSList *extensions = wtap_get_all_file_extensions_list(); + GSList *suffix; + for (suffix = extensions; suffix != NULL; suffix = g_slist_next(suffix)) { + /* Does the file name end with that extension? */ + const char *extension = (char *)suffix->data; + size_t extension_len = strlen(extension); + if (displayname_len > extension_len && + displayname[displayname_len - extension_len - 1] == '.' && + strcmp(&displayname[displayname_len - extension_len], extension) == 0) { + /* Yes. Strip the extension off, and return the result. */ + displayname[displayname_len - extension_len - 1] = '\0'; + return displayname; + } + } + } else { + displayname=g_strdup(""); + } + } else { + /* The file we read is a temporary file from a live capture or + a merge operation; we don't mention its name, but, if it's + from a capture, give the source of the capture. */ + if (cf->source) { + displayname = g_strdup(cf->source); + } else { + displayname = g_strdup(""); + } + } + return displayname; +} + void cf_set_tempfile_source(capture_file *cf, gchar *source) { if (cf->source) { g_free(cf->source); diff --git a/file.h b/file.h index 3088435a60..090528654b 100644 --- a/file.h +++ b/file.h @@ -275,6 +275,17 @@ cf_write_status_t cf_export_specified_packets(capture_file *cf, */ gchar *cf_get_display_name(capture_file *cf); +/** + * Get a name that can be used to generate a file name from the + * capture file name. It's based on the displayable name, so it's + * UTF-8; if it ends with a suffix that's used by a file type libwiretap + * can read, we strip that suffix off. + * + * @param cf the capture file + * @return the base name (must be g_free'd) + */ +gchar *cf_get_basename(capture_file *cf); + /** * Set the source of the capture data for temporary files, e.g. * "Interface eth0" or "Pipe from Pong" diff --git a/ui/qt/capture_file.cpp b/ui/qt/capture_file.cpp index 3aee4f557c..039ded83aa 100644 --- a/ui/qt/capture_file.cpp +++ b/ui/qt/capture_file.cpp @@ -160,16 +160,15 @@ const QString CaptureFile::fileName() const QString CaptureFile::fileBaseName() { - QString path, baseName; + QString baseName; - path = filePath(); - if (!path.isEmpty()) { - QFileInfo cfi(path); - baseName = cfi.baseName(); + if (isValid()) { + char *basename = cf_get_basename(cap_file_); + baseName = basename; + g_free(basename); } else { baseName = QString(); } - return baseName; } diff --git a/wiretap/file_access.c b/wiretap/file_access.c index cc29ed8eb7..5de6744e3a 100644 --- a/wiretap/file_access.c +++ b/wiretap/file_access.c @@ -1635,7 +1635,7 @@ static const struct file_type_subtype_info* dump_open_table = dump_open_table_ba * to the number of elements in the static table, but, if we have to * allocate the GArray, it's changed to have the size of the GArray. */ -gint wtap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct file_type_subtype_info); +static gint wtap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct file_type_subtype_info); /* * Pointer to the GArray; NULL until it's needed. @@ -2025,11 +2025,13 @@ add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions, /* * Add the default extension, and all compressed variants of - * it. + * it, if there is a default extension. */ - extensions = add_extensions(extensions, - dump_open_table[file_type_subtype].default_file_extension, - compressed_file_extensions); + if (dump_open_table[file_type_subtype].default_file_extension != NULL) { + extensions = add_extensions(extensions, + dump_open_table[file_type_subtype].default_file_extension, + compressed_file_extensions); + } if (dump_open_table[file_type_subtype].additional_file_extensions != NULL) { /* @@ -2095,10 +2097,37 @@ wtap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed return extensions; } +/* Return a list of all extensions that are used by all file types that + we can read, including compressed extensions, e.g. not just "pcap" but + also "pcap.gz" if we can read gzipped files. + + "File type" means "include file types that correspond to collections + of network packets, as well as file types that store data that just + happens to be transported over protocols such as HTTP but that aren't + collections of network packets, and plain text files". + + All strings in the list are allocated with g_malloc() and must be freed + with g_free(). */ +GSList * +wtap_get_all_file_extensions_list(void) +{ + GSList *extensions; + int i; + + extensions = NULL; /* empty list, to start with */ + + for (i = 0; i < WTAP_NUM_FILE_TYPES_SUBTYPES; i++) { + extensions = add_extensions_for_file_type_subtype(i, extensions, + compressed_file_extension_table); + } + + return extensions; +} + /* * Free a list returned by wtap_get_file_extension_type_extensions(), - * wtap_get_all_capture_file_extensions_list, or - * wtap_get_file_extensions_list(). + * wtap_get_all_capture_file_extensions_list, wtap_get_file_extensions_list(), + * or wtap_get_all_file_extensions_list(). */ void wtap_free_extensions_list(GSList *extensions) diff --git a/wiretap/wtap.h b/wiretap/wtap.h index ceedb762a8..d1beb85dfe 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -2004,6 +2004,8 @@ const char *wtap_default_file_extension(int filetype); WS_DLL_PUBLIC GSList *wtap_get_file_extensions_list(int filetype, gboolean include_compressed); WS_DLL_PUBLIC +GSList *wtap_get_all_file_extensions_list(void); +WS_DLL_PUBLIC void wtap_free_extensions_list(GSList *extensions); WS_DLL_PUBLIC