PageRenderTime 116ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 1ms

/epan/prefs.c

https://github.com/labx-technologies-llc/wireshark
C | 4657 lines | 3812 code | 369 blank | 476 comment | 223 complexity | 9b7d8c0299a094ae5c3b50a131d948b7 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /* prefs.c
  2. * Routines for handling preferences
  3. *
  4. * $Id$
  5. *
  6. * Wireshark - Network traffic analyzer
  7. * By Gerald Combs <gerald@wireshark.org>
  8. * Copyright 1998 Gerald Combs
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  23. */
  24. #include "config.h"
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <ctype.h>
  28. #include <errno.h>
  29. #ifdef HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #include <glib.h>
  33. #include <stdio.h>
  34. #include <epan/filesystem.h>
  35. #include <epan/address.h>
  36. #include <epan/addr_resolv.h>
  37. #include <epan/oids.h>
  38. #ifdef HAVE_GEOIP
  39. #include <epan/geoip_db.h>
  40. #endif
  41. #include <epan/packet.h>
  42. #include <epan/prefs.h>
  43. #include <epan/proto.h>
  44. #include <epan/strutil.h>
  45. #include <epan/column.h>
  46. #include "print.h"
  47. #include <wsutil/file_util.h>
  48. #include <epan/prefs-int.h>
  49. #include <epan/uat-int.h>
  50. #include "epan/filter_expressions.h"
  51. #include "epan/wmem/wmem.h"
  52. /* Internal functions */
  53. static module_t *find_subtree(module_t *parent, const char *tilte);
  54. static module_t *prefs_register_module_or_subtree(module_t *parent,
  55. const char *name, const char *title, const char *description, gboolean is_subtree,
  56. void (*apply_cb)(void), gboolean use_gui);
  57. static prefs_set_pref_e set_pref(gchar*, const gchar*, void *, gboolean);
  58. static char * join_string_list(GList *);
  59. static void free_col_info(GList *);
  60. static void pre_init_prefs(void);
  61. static gboolean prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt);
  62. static gboolean parse_column_format(fmt_data *cfmt, const char *fmt);
  63. static void try_convert_to_custom_column(gpointer *el_data);
  64. #define PF_NAME "preferences"
  65. #define OLD_GPF_NAME "wireshark.conf" /* old name for global preferences file */
  66. static gboolean prefs_initialized = FALSE;
  67. static gboolean prefs_pre_initialized = FALSE;
  68. static gchar *gpf_path = NULL;
  69. static gchar *cols_hidden_list = NULL;
  70. /*
  71. * XXX - variables to allow us to attempt to interpret the first
  72. * "mgcp.{tcp,udp}.port" in a preferences file as
  73. * "mgcp.{tcp,udp}.gateway_port" and the second as
  74. * "mgcp.{tcp,udp}.callagent_port".
  75. */
  76. static int mgcp_tcp_port_count;
  77. static int mgcp_udp_port_count;
  78. e_prefs prefs;
  79. static const enum_val_t gui_ptree_line_style[] = {
  80. {"NONE", "NONE", 0},
  81. {"SOLID", "SOLID", 1},
  82. {"DOTTED", "DOTTED", 2},
  83. {"TABBED", "TABBED", 3},
  84. {NULL, NULL, -1}
  85. };
  86. static const enum_val_t gui_ptree_expander_style[] = {
  87. {"NONE", "NONE", 0},
  88. {"SQUARE", "SQUARE", 1},
  89. {"TRIANGLE", "TRIANGLE", 2},
  90. {"CIRCULAR", "CIRCULAR", 3},
  91. {NULL, NULL, -1}
  92. };
  93. static const enum_val_t gui_hex_dump_highlight_style[] = {
  94. {"BOLD", "BOLD", 0},
  95. {"INVERSE", "INVERSE", 1},
  96. {NULL, NULL, -1}
  97. };
  98. static const enum_val_t gui_console_open_type[] = {
  99. {"NEVER", "NEVER", console_open_never},
  100. {"AUTOMATIC", "AUTOMATIC", console_open_auto},
  101. {"ALWAYS", "ALWAYS", console_open_always},
  102. {NULL, NULL, -1}
  103. };
  104. static const enum_val_t gui_version_placement_type[] = {
  105. {"WELCOME", "WELCOME", version_welcome_only},
  106. {"TITLE", "TITLE", version_title_only},
  107. {"BOTH", "BOTH", version_both},
  108. {"NEITHER", "NEITHER", version_neither},
  109. {NULL, NULL, -1}
  110. };
  111. static const enum_val_t gui_fileopen_style[] = {
  112. {"LAST_OPENED", "LAST_OPENED", 0},
  113. {"SPECIFIED", "SPECIFIED", 1},
  114. {NULL, NULL, -1}
  115. };
  116. /* GTK knows of two ways representing "both", vertical and horizontal aligned.
  117. * as this may not work on other guis, we use only "both" in general here */
  118. static const enum_val_t gui_toolbar_style[] = {
  119. {"ICONS", "ICONS", 0},
  120. {"TEXT", "TEXT", 1},
  121. {"BOTH", "BOTH", 2},
  122. {NULL, NULL, -1}
  123. };
  124. static const enum_val_t gui_layout_content[] = {
  125. {"NONE", "NONE", 0},
  126. {"PLIST", "PLIST", 1},
  127. {"PDETAILS", "PDETAILS", 2},
  128. {"PBYTES", "PBYTES", 3},
  129. {NULL, NULL, -1}
  130. };
  131. static const enum_val_t gui_update_channel[] = {
  132. {"DEVELOPMENT", "DEVELOPMENT", UPDATE_CHANNEL_DEVELOPMENT},
  133. {"STABLE", "STABLE", UPDATE_CHANNEL_STABLE},
  134. {NULL, NULL, -1}
  135. };
  136. #if defined(HAVE_PCAP_CREATE)
  137. /* Can set monitor mode and buffer size. */
  138. static gint num_capture_cols = 7;
  139. static const gchar *capture_cols[7] = {
  140. "INTERFACE",
  141. "LINK",
  142. "PMODE",
  143. "SNAPLEN",
  144. "MONITOR",
  145. "BUFFER",
  146. "FILTER"
  147. };
  148. #define CAPTURE_COL_TYPE_DESCRIPTION \
  149. "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
  150. #elif defined(_WIN32) && !defined (HAVE_PCAP_CREATE)
  151. /* Can set buffer size but not monitor mode. */
  152. static gint num_capture_cols = 6;
  153. static const gchar *capture_cols[6] = {
  154. "INTERFACE",
  155. "LINK",
  156. "PMODE",
  157. "SNAPLEN",
  158. "BUFFER",
  159. "FILTER"
  160. };
  161. #define CAPTURE_COL_TYPE_DESCRIPTION \
  162. "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, BUFFER, FILTER\n"
  163. #else
  164. /* Can neither set buffer size nor monitor mode. */
  165. static gint num_capture_cols = 5;
  166. static const gchar *capture_cols[5] = {
  167. "INTERFACE",
  168. "LINK",
  169. "PMODE",
  170. "SNAPLEN",
  171. "FILTER"
  172. };
  173. #define CAPTURE_COL_TYPE_DESCRIPTION \
  174. "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, FILTER\n"
  175. #endif
  176. /*
  177. * List of all modules with preference settings.
  178. */
  179. static wmem_tree_t *prefs_modules = NULL;
  180. /*
  181. * List of all modules that should show up at the top level of the
  182. * tree in the preference dialog box.
  183. */
  184. static wmem_tree_t *prefs_top_level_modules = NULL;
  185. /** Sets up memory used by proto routines. Called at program startup */
  186. void
  187. prefs_init(void)
  188. {
  189. prefs_modules = wmem_tree_new(wmem_epan_scope());
  190. prefs_top_level_modules = wmem_tree_new(wmem_epan_scope());
  191. }
  192. static void
  193. free_pref(gpointer data, gpointer user_data _U_)
  194. {
  195. pref_t *pref = (pref_t *)data;
  196. switch (pref->type) {
  197. case PREF_OBSOLETE:
  198. case PREF_BOOL:
  199. case PREF_ENUM:
  200. case PREF_UINT:
  201. case PREF_STATIC_TEXT:
  202. case PREF_UAT:
  203. case PREF_COLOR:
  204. break;
  205. case PREF_STRING:
  206. case PREF_FILENAME:
  207. case PREF_DIRNAME:
  208. g_free((char *)*pref->varp.string);
  209. *pref->varp.string = NULL;
  210. g_free(pref->default_val.string);
  211. pref->default_val.string = NULL;
  212. break;
  213. case PREF_RANGE:
  214. g_free(*pref->varp.range);
  215. *pref->varp.range = NULL;
  216. g_free(pref->default_val.range);
  217. pref->default_val.range = NULL;
  218. break;
  219. case PREF_CUSTOM:
  220. if (strcmp(pref->name, "columns") == 0)
  221. pref->stashed_val.boolval = TRUE;
  222. pref->custom_cbs.free_cb(pref);
  223. break;
  224. }
  225. g_free(pref);
  226. }
  227. static guint
  228. free_module_prefs(module_t *module, gpointer data _U_)
  229. {
  230. if (module->prefs) {
  231. g_list_foreach(module->prefs, free_pref, NULL);
  232. g_list_free(module->prefs);
  233. }
  234. module->prefs = NULL;
  235. module->numprefs = 0;
  236. if (module->submodules) {
  237. prefs_modules_foreach_submodules(module, free_module_prefs, NULL);
  238. }
  239. /* We don't free the actual module: its submodules pointer points to
  240. a wmem_tree and the module itself is stored in a wmem_tree
  241. */
  242. return 0;
  243. }
  244. /** Frees memory used by proto routines. Called at program shutdown */
  245. void
  246. prefs_cleanup(void)
  247. {
  248. /* This isn't strictly necessary since we're exiting anyway, but let's
  249. * do what clean up we can.
  250. */
  251. prefs_modules_foreach(free_module_prefs, NULL);
  252. }
  253. /*
  254. * Register a module that will have preferences.
  255. * Specify the module under which to register it or NULL to register it
  256. * at the top level, the name used for the module in the preferences file,
  257. * the title used in the tab for it in a preferences dialog box, and a
  258. * routine to call back when we apply the preferences.
  259. */
  260. module_t *
  261. prefs_register_module(module_t *parent, const char *name, const char *title,
  262. const char *description, void (*apply_cb)(void),
  263. const gboolean use_gui)
  264. {
  265. return prefs_register_module_or_subtree(parent, name, title, description,
  266. FALSE, apply_cb, use_gui);
  267. }
  268. /*
  269. * Register a subtree that will have modules under it.
  270. * Specify the module under which to register it or NULL to register it
  271. * at the top level and the title used in the tab for it in a preferences
  272. * dialog box.
  273. */
  274. module_t *
  275. prefs_register_subtree(module_t *parent, const char *title, const char *description,
  276. void (*apply_cb)(void))
  277. {
  278. return prefs_register_module_or_subtree(parent, NULL, title, description,
  279. TRUE, apply_cb,
  280. parent ? parent->use_gui : FALSE);
  281. }
  282. static module_t *
  283. prefs_register_module_or_subtree(module_t *parent, const char *name,
  284. const char *title, const char *description,
  285. gboolean is_subtree, void (*apply_cb)(void),
  286. gboolean use_gui)
  287. {
  288. module_t *module;
  289. const char *p;
  290. guchar c;
  291. /* this module may have been created as a subtree item previously */
  292. if ((module = find_subtree(parent, title))) {
  293. /* the module is currently a subtree */
  294. module->name = name;
  295. module->apply_cb = apply_cb;
  296. module->description = description;
  297. if (prefs_find_module(name) == NULL) {
  298. wmem_tree_insert_string(prefs_modules, name, module,
  299. WMEM_TREE_STRING_NOCASE);
  300. }
  301. return module;
  302. }
  303. module = wmem_new(wmem_epan_scope(), module_t);
  304. module->name = name;
  305. module->title = title;
  306. module->description = description;
  307. module->apply_cb = apply_cb;
  308. module->prefs = NULL; /* no preferences, to start */
  309. module->parent = parent;
  310. module->submodules = NULL; /* no submodules, to start */
  311. module->numprefs = 0;
  312. module->prefs_changed = FALSE;
  313. module->obsolete = FALSE;
  314. module->use_gui = use_gui;
  315. /*
  316. * Do we have a module name?
  317. */
  318. if (name != NULL) {
  319. /*
  320. * Yes.
  321. * Make sure that only lower-case ASCII letters, numbers,
  322. * underscores, hyphens, and dots appear in the name.
  323. *
  324. * Crash if there is, as that's an error in the code;
  325. * you can make the title a nice string with capitalization,
  326. * white space, punctuation, etc., but the name can be used
  327. * on the command line, and shouldn't require quoting,
  328. * shifting, etc.
  329. */
  330. for (p = name; (c = *p) != '\0'; p++)
  331. g_assert(isascii(c) &&
  332. (islower(c) || isdigit(c) || c == '_' ||
  333. c == '-' || c == '.'));
  334. /*
  335. * Make sure there's not already a module with that
  336. * name. Crash if there is, as that's an error in the
  337. * code, and the code has to be fixed not to register
  338. * more than one module with the same name.
  339. *
  340. * We search the list of all modules; the subtree stuff
  341. * doesn't require preferences in subtrees to have names
  342. * that reflect the subtree they're in (that would require
  343. * protocol preferences to have a bogus "protocol.", or
  344. * something such as that, to be added to all their names).
  345. */
  346. g_assert(prefs_find_module(name) == NULL);
  347. /*
  348. * Insert this module in the list of all modules.
  349. */
  350. wmem_tree_insert_string(prefs_modules, name, module, WMEM_TREE_STRING_NOCASE);
  351. } else {
  352. /*
  353. * This has no name, just a title; check to make sure it's a
  354. * subtree, and crash if it's not.
  355. */
  356. g_assert(is_subtree);
  357. }
  358. /*
  359. * Insert this module into the appropriate place in the display
  360. * tree.
  361. */
  362. if (parent == NULL) {
  363. /*
  364. * It goes at the top.
  365. */
  366. wmem_tree_insert_string(prefs_top_level_modules, title, module, WMEM_TREE_STRING_NOCASE);
  367. } else {
  368. /*
  369. * It goes into the list for this module.
  370. */
  371. if (parent->submodules == NULL)
  372. parent->submodules = wmem_tree_new(wmem_epan_scope());
  373. wmem_tree_insert_string(parent->submodules, title, module, WMEM_TREE_STRING_NOCASE);
  374. }
  375. return module;
  376. }
  377. /*
  378. * Register that a protocol has preferences.
  379. */
  380. module_t *protocols_module = NULL;
  381. module_t *
  382. prefs_register_protocol(int id, void (*apply_cb)(void))
  383. {
  384. protocol_t *protocol;
  385. /*
  386. * Have we yet created the "Protocols" subtree?
  387. */
  388. if (protocols_module == NULL) {
  389. /*
  390. * No. Register Protocols subtree as well as any preferences
  391. * for non-dissector modules.
  392. */
  393. prefs_register_modules();
  394. }
  395. protocol = find_protocol_by_id(id);
  396. return prefs_register_module(protocols_module,
  397. proto_get_protocol_filter_name(id),
  398. proto_get_protocol_short_name(protocol),
  399. proto_get_protocol_name(id), apply_cb, TRUE);
  400. }
  401. module_t *
  402. prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
  403. {
  404. protocol_t *protocol;
  405. module_t *subtree_module;
  406. module_t *new_module;
  407. char *sep = NULL, *ptr = NULL, *orig = NULL;
  408. /*
  409. * Have we yet created the "Protocols" subtree?
  410. * XXX - can we just do this by registering Protocols/{subtree}?
  411. * If not, why not?
  412. */
  413. if (protocols_module == NULL) {
  414. /*
  415. * No. Register Protocols subtree as well as any preferences
  416. * for non-dissector modules.
  417. */
  418. prefs_register_modules();
  419. }
  420. subtree_module = protocols_module;
  421. if (subtree) {
  422. /* take a copy of the buffer, orig keeps a base pointer while ptr
  423. * walks through the string */
  424. orig = ptr = g_strdup(subtree);
  425. while (ptr && *ptr) {
  426. if ((sep = strchr(ptr, '/')))
  427. *sep++ = '\0';
  428. if (!(new_module = find_subtree(subtree_module, ptr))) {
  429. /*
  430. * There's no such module; create it, with the description
  431. * being the name (if it's later registered explicitly
  432. * with a description, that will override it).
  433. */
  434. ptr = wmem_strdup(wmem_epan_scope(), ptr),
  435. new_module = prefs_register_subtree(subtree_module, ptr, ptr, NULL);
  436. }
  437. subtree_module = new_module;
  438. ptr = sep;
  439. }
  440. g_free(orig);
  441. }
  442. protocol = find_protocol_by_id(id);
  443. return prefs_register_module(subtree_module,
  444. proto_get_protocol_filter_name(id),
  445. proto_get_protocol_short_name(protocol),
  446. proto_get_protocol_name(id), apply_cb, TRUE);
  447. }
  448. /*
  449. * Register that a protocol used to have preferences but no longer does,
  450. * by creating an "obsolete" module for it.
  451. */
  452. module_t *
  453. prefs_register_protocol_obsolete(int id)
  454. {
  455. module_t *module;
  456. protocol_t *protocol;
  457. /*
  458. * Have we yet created the "Protocols" subtree?
  459. */
  460. if (protocols_module == NULL) {
  461. /*
  462. * No. Register Protocols subtree as well as any preferences
  463. * for non-dissector modules.
  464. */
  465. prefs_register_modules();
  466. }
  467. protocol = find_protocol_by_id(id);
  468. module = prefs_register_module(protocols_module,
  469. proto_get_protocol_filter_name(id),
  470. proto_get_protocol_short_name(protocol),
  471. proto_get_protocol_name(id), NULL, TRUE);
  472. module->obsolete = TRUE;
  473. return module;
  474. }
  475. /*
  476. * Register that a statistical tap has preferences.
  477. *
  478. * "name" is a name for the tap to use on the command line with "-o"
  479. * and in preference files.
  480. *
  481. * "title" is a short human-readable name for the tap.
  482. *
  483. * "description" is a longer human-readable description of the tap.
  484. */
  485. module_t *stats_module = NULL;
  486. module_t *
  487. prefs_register_stat(const char *name, const char *title,
  488. const char *description, void (*apply_cb)(void))
  489. {
  490. /*
  491. * Have we yet created the "Statistics" subtree?
  492. */
  493. if (stats_module == NULL) {
  494. /*
  495. * No. Register Statistics subtree as well as any preferences
  496. * for non-dissector modules.
  497. */
  498. prefs_register_modules();
  499. }
  500. return prefs_register_module(stats_module, name, title, description,
  501. apply_cb, TRUE);
  502. }
  503. module_t *
  504. prefs_find_module(const char *name)
  505. {
  506. return (module_t *)wmem_tree_lookup_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
  507. }
  508. static module_t *
  509. find_subtree(module_t *parent, const char *name)
  510. {
  511. return (module_t *)wmem_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, WMEM_TREE_STRING_NOCASE);
  512. }
  513. /*
  514. * Call a callback function, with a specified argument, for each module
  515. * in a list of modules. If the list is NULL, searches the top-level
  516. * list in the display tree of modules. If any callback returns a
  517. * non-zero value, we stop and return that value, otherwise we
  518. * return 0.
  519. *
  520. * Ignores "obsolete" modules; their sole purpose is to allow old
  521. * preferences for dissectors that no longer have preferences to be
  522. * silently ignored in preference files. Does not ignore subtrees,
  523. * as this can be used when walking the display tree of modules.
  524. */
  525. typedef struct {
  526. module_cb callback;
  527. gpointer user_data;
  528. guint ret;
  529. } call_foreach_t;
  530. static gboolean
  531. call_foreach_cb(void *value, void *data)
  532. {
  533. module_t *module = (module_t*)value;
  534. call_foreach_t *call_data = (call_foreach_t*)data;
  535. if (!module->obsolete)
  536. call_data->ret = (*call_data->callback)(module, call_data->user_data);
  537. return (call_data->ret != 0);
  538. }
  539. static guint
  540. prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
  541. gpointer user_data)
  542. {
  543. call_foreach_t call_data;
  544. if (module_list == NULL)
  545. module_list = prefs_top_level_modules;
  546. call_data.callback = callback;
  547. call_data.user_data = user_data;
  548. call_data.ret = 0;
  549. wmem_tree_foreach(module_list, call_foreach_cb, &call_data);
  550. return call_data.ret;
  551. }
  552. /*
  553. * Returns TRUE if module has any submodules
  554. */
  555. gboolean
  556. prefs_module_has_submodules(module_t *module)
  557. {
  558. if (module->submodules == NULL) {
  559. return FALSE;
  560. }
  561. if (wmem_tree_is_empty(module->submodules)) {
  562. return FALSE;
  563. }
  564. return TRUE;
  565. }
  566. /*
  567. * Call a callback function, with a specified argument, for each module
  568. * in the list of all modules. (This list does not include subtrees.)
  569. *
  570. * Ignores "obsolete" modules; their sole purpose is to allow old
  571. * preferences for dissectors that no longer have preferences to be
  572. * silently ignored in preference files.
  573. */
  574. guint
  575. prefs_modules_foreach(module_cb callback, gpointer user_data)
  576. {
  577. return prefs_module_list_foreach(prefs_modules, callback, user_data);
  578. }
  579. /*
  580. * Call a callback function, with a specified argument, for each submodule
  581. * of specified modules. If the module is NULL, goes through the top-level
  582. * list in the display tree of modules.
  583. *
  584. * Ignores "obsolete" modules; their sole purpose is to allow old
  585. * preferences for dissectors that no longer have preferences to be
  586. * silently ignored in preference files. Does not ignore subtrees,
  587. * as this can be used when walking the display tree of modules.
  588. */
  589. guint
  590. prefs_modules_foreach_submodules(module_t *module, module_cb callback,
  591. gpointer user_data)
  592. {
  593. return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data);
  594. }
  595. static gboolean
  596. call_apply_cb(void *value, void *data _U_)
  597. {
  598. module_t *module = (module_t *)value;
  599. if (module->obsolete)
  600. return FALSE;
  601. if (module->prefs_changed) {
  602. if (module->apply_cb != NULL)
  603. (*module->apply_cb)();
  604. module->prefs_changed = FALSE;
  605. }
  606. return FALSE;
  607. }
  608. /*
  609. * Call the "apply" callback function for each module if any of its
  610. * preferences have changed, and then clear the flag saying its
  611. * preferences have changed, as the module has been notified of that
  612. * fact.
  613. */
  614. void
  615. prefs_apply_all(void)
  616. {
  617. wmem_tree_foreach(prefs_modules, call_apply_cb, NULL);
  618. }
  619. /*
  620. * Call the "apply" callback function for a specific module if any of
  621. * its preferences have changed, and then clear the flag saying its
  622. * preferences have changed, as the module has been notified of that
  623. * fact.
  624. */
  625. void
  626. prefs_apply(module_t *module)
  627. {
  628. if (module && module->prefs_changed)
  629. call_apply_cb(module, NULL);
  630. }
  631. /*
  632. * Register a preference in a module's list of preferences.
  633. * If it has a title, give it an ordinal number; otherwise, it's a
  634. * preference that won't show up in the UI, so it shouldn't get an
  635. * ordinal number (the ordinal should be the ordinal in the set of
  636. * *visible* preferences).
  637. */
  638. static pref_t *
  639. register_preference(module_t *module, const char *name, const char *title,
  640. const char *description, pref_type_t type)
  641. {
  642. pref_t *preference;
  643. const gchar *p;
  644. preference = g_new(pref_t,1);
  645. preference->name = name;
  646. preference->title = title;
  647. preference->description = description;
  648. preference->type = type;
  649. if (title != NULL)
  650. preference->ordinal = module->numprefs;
  651. else
  652. preference->ordinal = -1; /* no ordinal for you */
  653. /*
  654. * Make sure that only lower-case ASCII letters, numbers,
  655. * underscores, and dots appear in the preference name.
  656. *
  657. * Crash if there is, as that's an error in the code;
  658. * you can make the title and description nice strings
  659. * with capitalization, white space, punctuation, etc.,
  660. * but the name can be used on the command line,
  661. * and shouldn't require quoting, shifting, etc.
  662. */
  663. for (p = name; *p != '\0'; p++)
  664. if (!(isascii((guchar)*p) &&
  665. (islower((guchar)*p) || isdigit((guchar)*p) || *p == '_' || *p == '.')))
  666. g_error("Preference %s.%s contains invalid characters", module->name, name);
  667. /*
  668. * Make sure there's not already a preference with that
  669. * name. Crash if there is, as that's an error in the
  670. * code, and the code has to be fixed not to register
  671. * more than one preference with the same name.
  672. */
  673. if (prefs_find_preference(module, name) != NULL)
  674. g_error("Preference %s has already been registered", name);
  675. if ((type != PREF_OBSOLETE) &&
  676. /* Don't compare if it's a subtree */
  677. (module->name != NULL)) {
  678. /*
  679. * Make sure the preference name doesn't begin with the
  680. * module name, as that's redundant and Just Silly.
  681. */
  682. if (!((strncmp(name, module->name, strlen(module->name)) != 0) ||
  683. (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_'))))
  684. g_error("Preference %s begins with the module name", name);
  685. }
  686. /*
  687. * There isn't already one with that name, so add the
  688. * preference.
  689. */
  690. module->prefs = g_list_append(module->prefs, preference);
  691. if (title != NULL)
  692. module->numprefs++;
  693. return preference;
  694. }
  695. /*
  696. * Find a preference in a module's list of preferences, given the module
  697. * and the preference's name.
  698. */
  699. typedef struct {
  700. GList *list_entry;
  701. const char *name;
  702. } find_pref_arg_t;
  703. static gint
  704. preference_match(gconstpointer a, gconstpointer b)
  705. {
  706. const pref_t *pref = (const pref_t *)a;
  707. const char *name = (const char *)b;
  708. return strcmp(name, pref->name);
  709. }
  710. static gboolean module_find_pref_cb(void *value, void *data)
  711. {
  712. find_pref_arg_t* arg = (find_pref_arg_t*)data;
  713. GList *list_entry;
  714. module_t *module = (module_t *)value;
  715. if (module == NULL)
  716. return FALSE;
  717. list_entry = g_list_find_custom(module->prefs, arg->name,
  718. preference_match);
  719. if (list_entry == NULL)
  720. return FALSE;
  721. arg->list_entry = list_entry;
  722. return TRUE;
  723. }
  724. struct preference *
  725. prefs_find_preference(module_t *module, const char *name)
  726. {
  727. find_pref_arg_t arg;
  728. GList *list_entry;
  729. if (module == NULL)
  730. return NULL; /* invalid parameters */
  731. list_entry = g_list_find_custom(module->prefs, name,
  732. preference_match);
  733. if (list_entry == NULL)
  734. {
  735. arg.list_entry = NULL;
  736. if (module->submodules != NULL)
  737. {
  738. arg.name = name;
  739. wmem_tree_foreach(module->submodules, module_find_pref_cb, &arg);
  740. }
  741. list_entry = arg.list_entry;
  742. }
  743. if (list_entry == NULL)
  744. return NULL; /* no such preference */
  745. return (struct preference *) list_entry->data;
  746. }
  747. /*
  748. * Returns TRUE if the given protocol has registered preferences
  749. */
  750. gboolean
  751. prefs_is_registered_protocol(const char *name)
  752. {
  753. module_t *m = prefs_find_module(name);
  754. return (m != NULL && !m->obsolete);
  755. }
  756. /*
  757. * Returns the module title of a registered protocol
  758. */
  759. const char *
  760. prefs_get_title_by_name(const char *name)
  761. {
  762. module_t *m = prefs_find_module(name);
  763. return (m != NULL && !m->obsolete) ? m->title : NULL;
  764. }
  765. /*
  766. * Register a preference with an unsigned integral value.
  767. */
  768. void
  769. prefs_register_uint_preference(module_t *module, const char *name,
  770. const char *title, const char *description,
  771. guint base, guint *var)
  772. {
  773. pref_t *preference;
  774. preference = register_preference(module, name, title, description,
  775. PREF_UINT);
  776. preference->varp.uint = var;
  777. preference->default_val.uint = *var;
  778. g_assert(base > 0 && base != 1 && base < 37);
  779. preference->info.base = base;
  780. }
  781. /*
  782. * XXX Add a prefs_register_{uint16|port}_preference which sets max_value?
  783. */
  784. /*
  785. * Register a "custom" preference with a unsigned integral value.
  786. * XXX - This should be temporary until we can find a better way
  787. * to do "custom" preferences
  788. */
  789. static void
  790. prefs_register_uint_custom_preference(module_t *module, const char *name,
  791. const char *title, const char *description,
  792. struct pref_custom_cbs* custom_cbs, guint *var)
  793. {
  794. pref_t *preference;
  795. preference = register_preference(module, name, title, description,
  796. PREF_CUSTOM);
  797. preference->custom_cbs = *custom_cbs;
  798. preference->varp.uint = var;
  799. preference->default_val.uint = *var;
  800. }
  801. /*
  802. * Register a preference with an Boolean value.
  803. */
  804. void
  805. prefs_register_bool_preference(module_t *module, const char *name,
  806. const char *title, const char *description,
  807. gboolean *var)
  808. {
  809. pref_t *preference;
  810. preference = register_preference(module, name, title, description,
  811. PREF_BOOL);
  812. preference->varp.boolp = var;
  813. preference->default_val.boolval = *var;
  814. }
  815. /*
  816. * Register a preference with an enumerated value.
  817. */
  818. void
  819. prefs_register_enum_preference(module_t *module, const char *name,
  820. const char *title, const char *description,
  821. gint *var, const enum_val_t *enumvals,
  822. gboolean radio_buttons)
  823. {
  824. pref_t *preference;
  825. preference = register_preference(module, name, title, description,
  826. PREF_ENUM);
  827. preference->varp.enump = var;
  828. preference->default_val.enumval = *var;
  829. preference->info.enum_info.enumvals = enumvals;
  830. preference->info.enum_info.radio_buttons = radio_buttons;
  831. }
  832. static pref_t*
  833. register_string_like_preference(module_t *module, const char *name,
  834. const char *title, const char *description,
  835. const char **var, pref_type_t type)
  836. {
  837. pref_t *preference;
  838. char *varcopy;
  839. preference = register_preference(module, name, title, description,
  840. type);
  841. /*
  842. * String preference values should be non-null (as you can't
  843. * keep them null after using the preferences GUI, you can at best
  844. * have them be null strings) and freeable (as we free them
  845. * if we change them).
  846. *
  847. * If the value is a null pointer, make it a copy of a null
  848. * string, otherwise make it a copy of the value.
  849. */
  850. if (*var == NULL) {
  851. *var = g_strdup("");
  852. varcopy = g_strdup("");
  853. } else {
  854. *var = g_strdup(*var);
  855. varcopy = g_strdup(*var);
  856. }
  857. preference->varp.string = var;
  858. preference->default_val.string = varcopy;
  859. preference->stashed_val.string = NULL;
  860. return preference;
  861. }
  862. /*
  863. * Register a preference with a character-string value.
  864. */
  865. void
  866. prefs_register_string_preference(module_t *module, const char *name,
  867. const char *title, const char *description,
  868. const char **var)
  869. {
  870. register_string_like_preference(module, name, title, description, var,
  871. PREF_STRING);
  872. }
  873. /*
  874. * Register a "custom" preference with a character-string value.
  875. * XXX - This should be temporary until we can find a better way
  876. * to do "custom" preferences
  877. */
  878. static
  879. void prefs_register_string_custom_preference(module_t *module, const char *name,
  880. const char *title, const char *description,
  881. struct pref_custom_cbs* custom_cbs, const char **var)
  882. {
  883. pref_t *preference;
  884. preference = register_string_like_preference(module, name, title, description, var,
  885. PREF_CUSTOM);
  886. preference->custom_cbs = *custom_cbs;
  887. }
  888. /*
  889. * Register a preference with a file name (string) value.
  890. */
  891. void
  892. prefs_register_filename_preference(module_t *module, const char *name,
  893. const char *title, const char *description,
  894. const char **var)
  895. {
  896. register_string_like_preference(module, name, title, description, var,
  897. PREF_FILENAME);
  898. }
  899. /*
  900. * Register a preference with a directory name (string) value.
  901. */
  902. void
  903. prefs_register_directory_preference(module_t *module, const char *name,
  904. const char *title, const char *description,
  905. const char **var)
  906. {
  907. register_string_like_preference(module, name, title, description, var,
  908. PREF_DIRNAME);
  909. }
  910. /*
  911. * Register a preference with a ranged value.
  912. */
  913. void
  914. prefs_register_range_preference(module_t *module, const char *name,
  915. const char *title, const char *description,
  916. range_t **var, guint32 max_value)
  917. {
  918. pref_t *preference;
  919. preference = register_preference(module, name, title, description,
  920. PREF_RANGE);
  921. preference->info.max_value = max_value;
  922. /*
  923. * Range preference values should be non-null (as you can't
  924. * keep them null after using the preferences GUI, you can at best
  925. * have them be empty ranges) and freeable (as we free them
  926. * if we change them).
  927. *
  928. * If the value is a null pointer, make it an empty range.
  929. */
  930. if (*var == NULL)
  931. *var = range_empty();
  932. preference->varp.range = var;
  933. preference->default_val.range = range_copy(*var);
  934. preference->stashed_val.range = NULL;
  935. }
  936. /*
  937. * Register a static text 'preference'. It can be used to add explanatory
  938. * text inline with other preferences in the GUI.
  939. * Note: Static preferences are not saved to the preferences file.
  940. */
  941. void
  942. prefs_register_static_text_preference(module_t *module, const char *name,
  943. const char *title,
  944. const char *description)
  945. {
  946. register_preference(module, name, title, description, PREF_STATIC_TEXT);
  947. }
  948. /*
  949. * Register a uat 'preference'. It adds a button that opens the uat's window in the
  950. * preferences tab of the module.
  951. */
  952. extern void
  953. prefs_register_uat_preference(module_t *module, const char *name,
  954. const char *title, const char *description,
  955. uat_t* uat)
  956. {
  957. pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
  958. preference->varp.uat = uat;
  959. }
  960. /*
  961. * Register a color preference.
  962. */
  963. void prefs_register_color_preference(module_t *module, const char *name,
  964. const char *title, const char *description, color_t *color)
  965. {
  966. pref_t* preference = register_preference(module, name, title, description, PREF_COLOR);
  967. preference->varp.colorp = color;
  968. preference->default_val.color = *color;
  969. }
  970. /*
  971. * Register a "custom" preference with a list.
  972. * XXX - This should be temporary until we can find a better way
  973. * to do "custom" preferences
  974. */
  975. typedef void (*pref_custom_list_init_cb) (pref_t* pref, GList** value);
  976. static
  977. void prefs_register_list_custom_preference(module_t *module, const char *name,
  978. const char *title, const char *description, struct pref_custom_cbs* custom_cbs,
  979. pref_custom_list_init_cb init_cb, GList** list)
  980. {
  981. pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
  982. preference->custom_cbs = *custom_cbs;
  983. init_cb(preference, list);
  984. }
  985. /*
  986. * Register a custom preference.
  987. */
  988. void prefs_register_custom_preference(module_t *module, const char *name,
  989. const char *title, const char *description, struct pref_custom_cbs* custom_cbs,
  990. void** custom_data _U_)
  991. {
  992. pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
  993. preference->custom_cbs = *custom_cbs;
  994. /* XXX - wait until we can handle void** pointers
  995. preference->custom_cbs.init_cb(preference, custom_data);
  996. */
  997. }
  998. /*
  999. * Register a preference that used to be supported but no longer is.
  1000. */
  1001. void
  1002. prefs_register_obsolete_preference(module_t *module, const char *name)
  1003. {
  1004. register_preference(module, name, NULL, NULL, PREF_OBSOLETE);
  1005. }
  1006. /*
  1007. * Check to see if a preference is obsolete.
  1008. */
  1009. extern gboolean
  1010. prefs_get_preference_obsolete(pref_t *pref)
  1011. {
  1012. if (pref)
  1013. return pref->type == PREF_OBSOLETE ? TRUE : FALSE;
  1014. return TRUE;
  1015. }
  1016. /*
  1017. * Make a preference obsolete.
  1018. */
  1019. extern prefs_set_pref_e
  1020. prefs_set_preference_obsolete(pref_t *pref)
  1021. {
  1022. if (pref) {
  1023. pref->type = PREF_OBSOLETE;
  1024. return PREFS_SET_OK;
  1025. }
  1026. return PREFS_SET_NO_SUCH_PREF;
  1027. }
  1028. /* Return the value assigned to the given uint preference. */
  1029. guint prefs_get_uint_preference(pref_t *pref)
  1030. {
  1031. if (pref && pref->type == PREF_UINT)
  1032. return *pref->varp.uint;
  1033. return 0;
  1034. }
  1035. /*
  1036. * Call a callback function, with a specified argument, for each preference
  1037. * in a given module.
  1038. *
  1039. * If any of the callbacks return a non-zero value, stop and return that
  1040. * value, otherwise return 0.
  1041. */
  1042. guint
  1043. prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data)
  1044. {
  1045. GList *elem;
  1046. pref_t *pref;
  1047. guint ret;
  1048. for (elem = g_list_first(module->prefs); elem != NULL; elem = g_list_next(elem)) {
  1049. pref = (pref_t *)elem->data;
  1050. if (pref->type == PREF_OBSOLETE) {
  1051. /*
  1052. * This preference is no longer supported; it's
  1053. * not a real preference, so we don't call the
  1054. * callback for it (i.e., we treat it as if it
  1055. * weren't found in the list of preferences,
  1056. * and we weren't called in the first place).
  1057. */
  1058. continue;
  1059. }
  1060. ret = (*callback)(pref, user_data);
  1061. if (ret != 0)
  1062. return ret;
  1063. }
  1064. return 0;
  1065. }
  1066. static const enum_val_t print_format_vals[] = {
  1067. { "text", "Plain Text", PR_FMT_TEXT },
  1068. { "postscript", "Postscript", PR_FMT_PS },
  1069. { NULL, NULL, 0 }
  1070. };
  1071. static const enum_val_t print_dest_vals[] = {
  1072. #ifdef _WIN32
  1073. /* "PR_DEST_CMD" means "to printer" on Windows */
  1074. { "command", "Printer", PR_DEST_CMD },
  1075. #else
  1076. { "command", "Command", PR_DEST_CMD },
  1077. #endif
  1078. { "file", "File", PR_DEST_FILE },
  1079. { NULL, NULL, 0 }
  1080. };
  1081. static void stats_callback(void)
  1082. {
  1083. /* Test for a sane tap update interval */
  1084. if (prefs.tap_update_interval < 100 || prefs.tap_update_interval > 10000)
  1085. prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
  1086. #ifdef HAVE_LIBPORTAUDIO
  1087. /* Test for a sane max channels entry */
  1088. if (prefs.rtp_player_max_visible < 1 || prefs.rtp_player_max_visible > 10)
  1089. prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
  1090. #endif
  1091. }
  1092. static void gui_callback(void)
  1093. {
  1094. /* Ensure there is at least one file count */
  1095. if (prefs.gui_recent_files_count_max == 0)
  1096. prefs.gui_recent_files_count_max = 10;
  1097. /* Ensure there is at least one display filter entry */
  1098. if (prefs.gui_recent_df_entries_max == 0)
  1099. prefs.gui_recent_df_entries_max = 10;
  1100. }
  1101. static void gui_layout_callback(void)
  1102. {
  1103. if (prefs.gui_layout_type == layout_unused ||
  1104. prefs.gui_layout_type >= layout_type_max) {
  1105. /* XXX - report an error? It's not a syntax error - we'd need to
  1106. add a way of reporting a *semantic* error. */
  1107. prefs.gui_layout_type = layout_type_5;
  1108. }
  1109. }
  1110. /******************************************************
  1111. * All custom preference function callbacks
  1112. ******************************************************/
  1113. static void custom_pref_no_cb(pref_t* pref _U_) {}
  1114. /*
  1115. * Console log level custom preference functions
  1116. */
  1117. static void console_log_level_reset_cb(pref_t* pref)
  1118. {
  1119. *pref->varp.uint = pref->default_val.uint;
  1120. }
  1121. static prefs_set_pref_e console_log_level_set_cb(pref_t* pref, const gchar* value, gboolean* changed)
  1122. {
  1123. guint uval;
  1124. uval = (guint)strtoul(value, NULL, 10);
  1125. if (*pref->varp.uint != uval) {
  1126. *changed = TRUE;
  1127. *pref->varp.uint = uval;
  1128. }
  1129. if (*pref->varp.uint & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG)) {
  1130. /*
  1131. * GLib >= 2.32 drops INFO and DEBUG messages by default. Tell
  1132. * it not to do that.
  1133. */
  1134. g_setenv("G_MESSAGES_DEBUG", "all", TRUE);
  1135. }
  1136. return PREFS_SET_OK;
  1137. }
  1138. static const char * console_log_level_type_name_cb(void) {
  1139. return "Log level";
  1140. }
  1141. static char * console_log_level_type_description_cb(void) {
  1142. return g_strdup_printf(
  1143. "Console log level (for debugging)\n"
  1144. "A bitmask of log levels:\n"
  1145. "ERROR = 4\n"
  1146. "CRITICAL = 8\n"
  1147. "WARNING = 16\n"
  1148. "MESSAGE = 32\n"
  1149. "INFO = 64\n"
  1150. "DEBUG = 128");
  1151. }
  1152. static gboolean console_log_level_is_default_cb(pref_t* pref) {
  1153. return *pref->varp.uint == pref->default_val.uint;
  1154. }
  1155. static char * console_log_level_to_str_cb(pref_t* pref, gboolean default_val) {
  1156. return g_strdup_printf("%u", default_val ? pref->default_val.uint : *pref->varp.uint);
  1157. }
  1158. /*
  1159. * Column preference functions
  1160. */
  1161. #define PRS_COL_HIDDEN "column.hidden"
  1162. #define PRS_COL_FMT "column.format"
  1163. #define PRS_COL_NUM "column.number"
  1164. static module_t *gui_column_module = NULL;
  1165. static void column_hidden_free_cb(pref_t* pref)
  1166. {
  1167. g_free((char *)*pref->varp.string);
  1168. *pref->varp.string = NULL;
  1169. g_free(pref->default_val.string);
  1170. pref->default_val.string = NULL;
  1171. }
  1172. static void column_hidden_reset_cb(pref_t* pref)
  1173. {
  1174. g_free((void *)*pref->varp.string);
  1175. *pref->varp.string = g_strdup(pref->default_val.string);
  1176. }
  1177. static prefs_set_pref_e column_hidden_set_cb(pref_t* pref, const gchar* value, gboolean* changed)
  1178. {
  1179. GList *clp;
  1180. fmt_data *cfmt;
  1181. pref_t *format_pref;
  1182. if (*pref->varp.string) {
  1183. if (strcmp(*pref->varp.string, value) != 0) {
  1184. *changed = TRUE;
  1185. g_free((void *)*pref->varp.string);
  1186. *pref->varp.string = g_strdup(value);
  1187. }
  1188. } else if (value) {
  1189. *pref->varp.string = g_strdup(value);
  1190. }
  1191. /*
  1192. * Set the "visible" flag for the existing columns; we need to
  1193. * do this if we set PRS_COL_HIDDEN but don't set PRS_COL_FMT
  1194. * after setting it (which might be the case if, for example, we
  1195. * set PRS_COL_HIDDEN on the command line).
  1196. */
  1197. format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
  1198. for (clp = *format_pref->varp.list; clp != NULL; clp = clp->next) {
  1199. cfmt = (fmt_data *)clp->data;
  1200. cfmt->visible = prefs_is_column_visible(*pref->varp.string, cfmt);
  1201. }
  1202. return PREFS_SET_OK;
  1203. }
  1204. static const char * column_hidden_type_name_cb(void) {
  1205. return "Packet list hidden columns";
  1206. }
  1207. static char * column_hidden_type_description_cb(void) {
  1208. return g_strdup("List all columns to hide in the packet list.");
  1209. }
  1210. static char * column_hidden_to_str_cb(pref_t* pref, gboolean default_val) {
  1211. GString *cols_hidden = g_string_new ("");
  1212. GList *clp;
  1213. fmt_data *cfmt;
  1214. pref_t *format_pref;
  1215. if (default_val)
  1216. return g_strdup(pref->default_val.string);
  1217. format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
  1218. clp = (format_pref) ? *format_pref->varp.list : NULL;
  1219. while (clp) {
  1220. gchar *prefs_fmt;
  1221. cfmt = (fmt_data *) clp->data;
  1222. if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_field)) {
  1223. prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
  1224. col_format_to_string(cfmt->fmt),
  1225. cfmt->custom_field,
  1226. cfmt->custom_occurrence,
  1227. cfmt->resolved ? 'R' : 'U');
  1228. } else {
  1229. prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
  1230. }
  1231. if (!cfmt->visible) {
  1232. if (cols_hidden->len)
  1233. g_string_append (cols_hidden, ",");
  1234. g_string_append (cols_hidden, prefs_fmt);
  1235. }
  1236. clp = clp->next;
  1237. }
  1238. return g_string_free (cols_hidden, FALSE);
  1239. }
  1240. static gboolean column_hidden_is_default_cb(pref_t* pref) {
  1241. char *cur_hidden_str = column_hidden_to_str_cb(pref, FALSE);
  1242. gboolean is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
  1243. g_free(cur_hidden_str);
  1244. return is_default;
  1245. }
  1246. /* Number of columns "preference". This is only used internally and is not written to the
  1247. * preference file
  1248. */
  1249. static void column_num_reset_cb(pref_t* pref)
  1250. {
  1251. *pref->varp.uint = pref->default_val.uint;
  1252. }
  1253. static prefs_set_pref_e column_num_set_cb(pref_t* pref _U_, const gchar* value _U_, gboolean* changed _U_)
  1254. {
  1255. /* Don't write this to the preferences file */
  1256. return PREFS_SET_OK;
  1257. }
  1258. static const char * column_num_type_name_cb(void) {
  1259. return NULL;
  1260. }
  1261. static char * column_num_type_description_cb(void) {
  1262. return g_strdup("");
  1263. }
  1264. static gboolean column_num_is_default_cb(pref_t* pref _U_) {
  1265. return TRUE;
  1266. }
  1267. static char * column_num_to_str_cb(pref_t* pref _U_, gboolean default_val _U_) {
  1268. return g_strdup("");
  1269. }
  1270. /*
  1271. * Column format custom preference functions
  1272. */
  1273. static void column_format_init_cb(pref_t* pref, GList** value)
  1274. {
  1275. fmt_data *src_cfmt, *dest_cfmt;
  1276. GList *entry;
  1277. pref->varp.list = value;
  1278. pref->default_val.list = NULL;
  1279. for (entry = *pref->varp.list; entry != NULL; entry = g_list_next(entry)) {
  1280. src_cfmt = (fmt_data *)entry->data;
  1281. dest_cfmt = g_new(fmt_data,1);
  1282. dest_cfmt->title = g_strdup(src_cfmt->title);
  1283. dest_cfmt->fmt = src_cfmt->fmt;
  1284. if (src_cfmt->custom_field) {
  1285. dest_cfmt->custom_field = g_strdup(src_cfmt->custom_field);
  1286. dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
  1287. } else {
  1288. dest_cfmt->custom_field = NULL;
  1289. dest_cfmt->custom_occurrence = 0;
  1290. }
  1291. dest_cfmt->visible = src_cfmt->visible;
  1292. dest_cfmt->resolved = src_cfmt->resolved;
  1293. pref->default_val.list = g_list_append(pref->default_val.list, dest_cfmt);
  1294. }
  1295. }
  1296. static void column_format_free_cb(pref_t* pref)
  1297. {
  1298. free_col_info(*pref->varp.list);
  1299. free_col_info(pref->default_val.list);
  1300. }
  1301. static void column_format_reset_cb(pref_t* pref)
  1302. {
  1303. fmt_data *src_cfmt, *dest_cfmt;
  1304. GList *entry;
  1305. pref_t *col_num_pref;
  1306. free_col_info(*pref->varp.list);
  1307. *pref->varp.list = NULL;
  1308. for (entry = pref->default_val.list; entry != NULL; entry = g_list_next(entry)) {
  1309. src_cfmt = (fmt_data *)entry->data;
  1310. dest_cfmt = g_new(fmt_data,1);
  1311. dest_cfmt->title = g_strdup(src_cfmt->title);
  1312. dest_cfmt->fmt = src_cfmt->fmt;
  1313. if (src_cfmt->custom_field) {
  1314. dest_cfmt->custom_field = g_strdup(src_cfmt->custom_field);
  1315. dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
  1316. } else {
  1317. dest_cfmt->custom_field = NULL;
  1318. dest_cfmt->custom_occurrence = 0;
  1319. }
  1320. dest_cfmt->visible = src_cfmt->visible;
  1321. dest_cfmt->resolved = src_cfmt->resolved;
  1322. *pref->varp.list = g_list_append(*pref->varp.list, dest_cfmt);
  1323. }
  1324. col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
  1325. column_num_reset_cb(col_num_pref);
  1326. }
  1327. static prefs_set_pref_e column_format_set_cb(pref_t* pref, const gchar* value, gboolean* changed _U_)
  1328. {
  1329. GList *col_l, *col_l_elt;
  1330. fmt_data *cfmt;
  1331. gint llen;
  1332. pref_t *hidden_pref, *col_num_pref;
  1333. col_l = prefs_get_string_list(value);
  1334. if (col_l == NULL)
  1335. return PREFS_SET_SYNTAX_ERR;
  1336. if ((g_list_length(col_l) % 2) != 0) {
  1337. /* A title didn't have a matching format. */
  1338. prefs_clear_string_list(col_l);
  1339. return PREFS_SET_SYNTAX_ERR;
  1340. }
  1341. /* Check to make sure all column formats are valid. */
  1342. col_l_elt = g_list_first(col_l);
  1343. while (col_l_elt) {
  1344. fmt_data cfmt_check;
  1345. /* Go past the title. */
  1346. col_l_elt = col_l_elt->next;
  1347. /* Parse the format to see if it's valid. */
  1348. if (!parse_column_format(&cfmt_check, (char *)col_l_elt->data)) {
  1349. /* It's not a valid column format. */
  1350. prefs_clear_string_list(col_l);
  1351. return PREFS_SET_SYNTAX_ERR;
  1352. }
  1353. if (cfmt_check.fmt != COL_CUSTOM) {
  1354. /* Some predefined columns have been migrated to use custom columns.
  1355. * We'll convert these silently here */
  1356. try_convert_to_custom_column(&col_l_elt->data);
  1357. } else {
  1358. /* We don't need the custom column field on this pass. */
  1359. g_free(cfmt_check.custom_field);
  1360. }
  1361. /* Go past the format. */
  1362. col_l_elt = col_l_elt->next;
  1363. }
  1364. /* They're all valid; process them. */
  1365. free_col_info(*pref->varp.list);
  1366. *pref->varp.list = NULL;
  1367. hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN);
  1368. col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
  1369. llen = g_list_length(col_l);
  1370. *col_num_pref->varp.uint = llen / 2;
  1371. col_l_elt = g_list_first(col_l);
  1372. while (col_l_elt) {
  1373. cfmt = g_new(fmt_data,1);
  1374. cfmt->title = g_strdup((gchar *)col_l_elt->data);
  1375. col_l_elt = col_l_elt->next;
  1376. parse_column_format(cfmt, (char *)col_l_elt->data);
  1377. cfmt->visible = prefs_is_column_visible((gchar*)(*hidden_pref->varp.string), cfmt);
  1378. col_l_elt = col_l_elt->next;
  1379. *pref->varp.list = g_list_append(*pref->varp.list, cfmt);
  1380. }
  1381. prefs_clear_string_list(col_l);
  1382. column_hidden_free_cb(hidden_pref);
  1383. return PREFS_SET_OK;
  1384. }
  1385. static const char * column_format_type_name_cb(void) {
  1386. return "Packet list column format";
  1387. }
  1388. static char * column_format_type_description_cb(void) {
  1389. return g_strdup("Each pair of strings consists of a column title and its format");
  1390. }
  1391. static gboolean column_format_is_default_cb(pref_t* pref) {
  1392. GList *clp = *pref->varp.list,
  1393. *pref_col = g_list_first(clp),
  1394. *def_col = g_list_first(pref->default_val.list);
  1395. fmt_data *cfmt, *def_cfmt;
  1396. gboolean is_default = TRUE;
  1397. pref_t *col_num_pref;
  1398. /* See if the column data has changed from the default */
  1399. col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
  1400. if (col_num_pref && *col_num_pref->varp.uint != col_num_pref->default_val.uint) {
  1401. is_default = FALSE;
  1402. } else {
  1403. while (pref_col && def_col) {
  1404. cfmt = (fmt_data *) pref_col->data;
  1405. def_cfmt = (fmt_data *) def_col->data;
  1406. if ((g_strcmp0(cfmt->title, def_cfmt->title) != 0) ||
  1407. (cfmt->fmt != def_cfmt->fmt) ||
  1408. (((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_field)) &&
  1409. ((g_strcmp0(cfmt->custom_field, def_cfmt->custom_field) != 0) ||
  1410. (cfmt->resolved != def_cfmt->resolved)))) {
  1411. is_default = FALSE;
  1412. break;
  1413. }
  1414. pref_col = pref_col->next;
  1415. def_col = def_col->next;
  1416. }
  1417. }
  1418. return is_default;
  1419. }
  1420. static char * column_format_to_str_cb(pref_t* pref, gboolean default_val) {
  1421. GList *pref_l = default_val ? pref->default_val.list : *pref->varp.list;
  1422. GList *clp = g_list_first(pref_l);
  1423. GList *col_l;
  1424. fmt_data *cfmt;
  1425. gchar *prefs_fmt;
  1426. char *column_format_str;
  1427. col_l = NULL;
  1428. while (clp) {
  1429. cfmt = (fmt_data *) clp->data;

Large files files are truncated, but you can click here to view the full file