1 /* column.c
2 * Routines for handling column preferences
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "config.h"
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <errno.h>
16
17 #ifdef HAVE_UNISTD_H
18 #include <unistd.h>
19 #endif
20
21 #include <epan/timestamp.h>
22 #include <epan/prefs.h>
23 #include <epan/dfilter/dfilter.h>
24 #include <epan/column.h>
25 #include <epan/packet.h>
26 #include <wsutil/ws_assert.h>
27
28 /* Given a format number (as defined in column-utils.h), returns its equivalent
29 string */
30 const gchar *
col_format_to_string(const gint fmt)31 col_format_to_string(const gint fmt) {
32 static const gchar *const slist[NUM_COL_FMTS] = {
33 "%q", /* 0) COL_8021Q_VLAN_ID */
34 "%Yt", /* 1) COL_ABS_YMD_TIME */
35 "%YDOYt", /* 2) COL_ABS_YDOY_TIME */
36 "%At", /* 3) COL_ABS_TIME */
37 "%V", /* 4) COL_VSAN - !! DEPRECATED !!*/
38 "%B", /* 5) COL_CUMULATIVE_BYTES */
39 "%Cus", /* 6) COL_CUSTOM */
40 "%y", /* 7) COL_DCE_CALL */
41 "%Tt", /* 8) COL_DELTA_TIME */
42 "%Gt", /* 9) COL_DELTA_TIME_DIS */
43 "%rd", /* 10) COL_RES_DST */
44 "%ud", /* 11) COL_UNRES_DST */
45 "%rD", /* 12) COL_RES_DST_PORT */
46 "%uD", /* 13) COL_UNRES_DST_PORT */
47 "%d", /* 14) COL_DEF_DST */
48 "%D", /* 15) COL_DEF_DST_PORT */
49 "%a", /* 16) COL_EXPERT */
50 "%I", /* 17) COL_IF_DIR */
51 "%F", /* 18) COL_FREQ_CHAN */
52 "%hd", /* 19) COL_DEF_DL_DST */
53 "%hs", /* 20) COL_DEF_DL_SRC */
54 "%rhd", /* 21) COL_RES_DL_DST */
55 "%uhd", /* 22) COL_UNRES_DL_DST */
56 "%rhs", /* 23) COL_RES_DL_SRC*/
57 "%uhs", /* 24) COL_UNRES_DL_SRC */
58 "%e", /* 25) COL_RSSI */
59 "%x", /* 26) COL_TX_RATE */
60 "%f", /* 27) COL_DSCP_VALUE */
61 "%i", /* 28) COL_INFO */
62 "%rnd", /* 29) COL_RES_NET_DST */
63 "%und", /* 30) COL_UNRES_NET_DST */
64 "%rns", /* 31) COL_RES_NET_SRC */
65 "%uns", /* 32) COL_UNRES_NET_SRC */
66 "%nd", /* 33) COL_DEF_NET_DST */
67 "%ns", /* 34) COL_DEF_NET_SRC */
68 "%m", /* 35) COL_NUMBER */
69 "%L", /* 36) COL_PACKET_LENGTH */
70 "%p", /* 37) COL_PROTOCOL */
71 "%Rt", /* 38) COL_REL_TIME */
72 "%s", /* 39) COL_DEF_SRC */
73 "%S", /* 40) COL_DEF_SRC_PORT */
74 "%rs", /* 41) COL_RES_SRC */
75 "%us", /* 42) COL_UNRES_SRC */
76 "%rS", /* 43) COL_RES_SRC_PORT */
77 "%uS", /* 44) COL_UNRES_SRC_PORT */
78 "%E", /* 45) COL_TEI */
79 "%Yut", /* 46) COL_UTC_YMD_TIME */
80 "%YDOYut", /* 47) COL_UTC_YDOY_TIME */
81 "%Aut", /* 48) COL_UTC_TIME */
82 "%t" /* 49) COL_CLS_TIME */
83 };
84
85 /* The following formats have been used in deprecated columns. Noted here
86 * so they aren't reused
87 *
88 * "%U", COL_COS_VALUE
89 * "%c", COL_CIRCUIT_ID
90 * "%l", COL_BSSGP_TLLI
91 * "%H", COL_HPUX_SUBSYS
92 * "%P", COL_HPUX_DEVID
93 * "%C", COL_FR_DLCI
94 * "%rct", COL_REL_CONV_TIME
95 * "%dct", COL_DELTA_CONV_TIME
96 * "%XO", COL_OXID
97 * "%XR", COL_RXID
98 * "%Xd", COL_SRCIDX
99 * "%Xs", COL_DSTIDX
100 * "%z", COL_DCE_CTX
101 */
102 if (fmt < 0 || fmt >= NUM_COL_FMTS)
103 return NULL;
104
105 return(slist[fmt]);
106 }
107
108 /* Given a format number (as defined in column-utils.h), returns its
109 description */
110 const gchar *
col_format_desc(const gint fmt_num)111 col_format_desc(const gint fmt_num) {
112
113 /* This should be sorted alphabetically, e.g. `sort -t, -k2` */
114 /*
115 * This is currently used in the preferences UI, so out-of-numeric-order
116 * performance shouldn't be an issue.
117 */
118 static const value_string dlist_vals[] = {
119
120 { COL_8021Q_VLAN_ID, "802.1Q VLAN id" },
121 { COL_ABS_YMD_TIME, "Absolute date, as YYYY-MM-DD, and time" },
122 { COL_ABS_YDOY_TIME, "Absolute date, as YYYY/DOY, and time" },
123 { COL_ABS_TIME, "Absolute time" },
124 { COL_VSAN, "Cisco VSAN" },
125 { COL_CUMULATIVE_BYTES, "Cumulative Bytes" },
126 { COL_CUSTOM, "Custom" },
127 { COL_DCE_CALL, "DCE/RPC call (cn_call_id / dg_seqnum)" },
128 { COL_DELTA_TIME_DIS, "Delta time displayed" },
129 { COL_DELTA_TIME, "Delta time" },
130 { COL_RES_DST, "Dest addr (resolved)" },
131 { COL_UNRES_DST, "Dest addr (unresolved)" },
132 { COL_RES_DST_PORT, "Dest port (resolved)" },
133 { COL_UNRES_DST_PORT, "Dest port (unresolved)" },
134 { COL_DEF_DST, "Destination address" },
135 { COL_DEF_DST_PORT, "Destination port" },
136 { COL_EXPERT, "Expert Info Severity" },
137 { COL_IF_DIR, "FW-1 monitor if/direction" },
138 { COL_FREQ_CHAN, "Frequency/Channel" },
139 { COL_DEF_DL_DST, "Hardware dest addr" },
140 { COL_DEF_DL_SRC, "Hardware src addr" },
141 { COL_RES_DL_DST, "Hw dest addr (resolved)" },
142 { COL_UNRES_DL_DST, "Hw dest addr (unresolved)" },
143 { COL_RES_DL_SRC, "Hw src addr (resolved)" },
144 { COL_UNRES_DL_SRC, "Hw src addr (unresolved)" },
145 { COL_RSSI, "IEEE 802.11 RSSI" },
146 { COL_TX_RATE, "IEEE 802.11 TX rate" },
147 { COL_DSCP_VALUE, "IP DSCP Value" },
148 { COL_INFO, "Information" },
149 { COL_RES_NET_DST, "Net dest addr (resolved)" },
150 { COL_UNRES_NET_DST, "Net dest addr (unresolved)" },
151 { COL_RES_NET_SRC, "Net src addr (resolved)" },
152 { COL_UNRES_NET_SRC, "Net src addr (unresolved)" },
153 { COL_DEF_NET_DST, "Network dest addr" },
154 { COL_DEF_NET_SRC, "Network src addr" },
155 { COL_NUMBER, "Number" },
156 { COL_PACKET_LENGTH, "Packet length (bytes)" },
157 { COL_PROTOCOL, "Protocol" },
158 { COL_REL_TIME, "Relative time" },
159 { COL_DEF_SRC, "Source address" },
160 { COL_DEF_SRC_PORT, "Source port" },
161 { COL_RES_SRC, "Src addr (resolved)" },
162 { COL_UNRES_SRC, "Src addr (unresolved)" },
163 { COL_RES_SRC_PORT, "Src port (resolved)" },
164 { COL_UNRES_SRC_PORT, "Src port (unresolved)" },
165 { COL_TEI, "TEI" },
166 { COL_CLS_TIME, "Time (format as specified)" },
167 { COL_UTC_YMD_TIME, "UTC date, as YYYY-MM-DD, and time" },
168 { COL_UTC_YDOY_TIME, "UTC date, as YYYY/DOY, and time" },
169 { COL_UTC_TIME, "UTC time" },
170
171 { 0, NULL }
172 };
173
174 const gchar *val_str = try_val_to_str(fmt_num, dlist_vals);
175 ws_assert(val_str != NULL);
176 return val_str;
177 }
178
179 void
column_dump_column_formats(void)180 column_dump_column_formats(void)
181 {
182 gint fmt;
183
184 for (fmt = 0; fmt < NUM_COL_FMTS; fmt++) {
185 printf("%s\t%s\n", col_format_to_string(fmt), col_format_desc(fmt));
186 }
187
188 printf("\nFor example, to print Wireshark's default columns with tshark:\n\n"
189 #ifdef _WIN32
190 "tshark.exe -o \"gui.column.format:"
191 "\\\"No.\\\",\\\"%%m\\\","
192 "\\\"Time\\\",\\\"%%t\\\","
193 "\\\"Source\\\",\\\"%%s\\\","
194 "\\\"Destination\\\",\\\"%%d\\\","
195 "\\\"Protocol\\\",\\\"%%p\\\","
196 "\\\"Length\\\",\\\"%%L\\\","
197 "\\\"Info\\\",\\\"%%i\\\"\"\n");
198 #else
199 "tshark -o 'gui.column.format:"
200 "\"No.\",\"%%m\","
201 "\"Time\",\"%%t\","
202 "\"Source\",\"%%s\","
203 "\"Destination\",\"%%d\","
204 "\"Protocol\",\"%%p\","
205 "\"Length\",\"%%L\","
206 "\"Info\",\"%%i\"'\n");
207 #endif
208 }
209
210 /* Marks each array element true if it can be substituted for the given
211 column format */
212 void
get_column_format_matches(gboolean * fmt_list,const gint format)213 get_column_format_matches(gboolean *fmt_list, const gint format) {
214
215 /* Get the obvious: the format itself */
216 if ((format >= 0) && (format < NUM_COL_FMTS))
217 fmt_list[format] = TRUE;
218
219 /* Get any formats lower down on the chain */
220 switch (format) {
221 case COL_DEF_SRC:
222 fmt_list[COL_RES_DL_SRC] = TRUE;
223 fmt_list[COL_RES_NET_SRC] = TRUE;
224 break;
225 case COL_RES_SRC:
226 fmt_list[COL_RES_DL_SRC] = TRUE;
227 fmt_list[COL_RES_NET_SRC] = TRUE;
228 break;
229 case COL_UNRES_SRC:
230 fmt_list[COL_UNRES_DL_SRC] = TRUE;
231 fmt_list[COL_UNRES_NET_SRC] = TRUE;
232 break;
233 case COL_DEF_DST:
234 fmt_list[COL_RES_DL_DST] = TRUE;
235 fmt_list[COL_RES_NET_DST] = TRUE;
236 break;
237 case COL_RES_DST:
238 fmt_list[COL_RES_DL_DST] = TRUE;
239 fmt_list[COL_RES_NET_DST] = TRUE;
240 break;
241 case COL_UNRES_DST:
242 fmt_list[COL_UNRES_DL_DST] = TRUE;
243 fmt_list[COL_UNRES_NET_DST] = TRUE;
244 break;
245 case COL_DEF_DL_SRC:
246 fmt_list[COL_RES_DL_SRC] = TRUE;
247 break;
248 case COL_DEF_DL_DST:
249 fmt_list[COL_RES_DL_DST] = TRUE;
250 break;
251 case COL_DEF_NET_SRC:
252 fmt_list[COL_RES_NET_SRC] = TRUE;
253 break;
254 case COL_DEF_NET_DST:
255 fmt_list[COL_RES_NET_DST] = TRUE;
256 break;
257 case COL_DEF_SRC_PORT:
258 fmt_list[COL_RES_SRC_PORT] = TRUE;
259 break;
260 case COL_DEF_DST_PORT:
261 fmt_list[COL_RES_DST_PORT] = TRUE;
262 break;
263 default:
264 break;
265 }
266 }
267
268 /* Returns a string representing the longest possible value for
269 a timestamp column type. */
270 static const char *
get_timestamp_column_longest_string(const gint type,const gint precision)271 get_timestamp_column_longest_string(const gint type, const gint precision)
272 {
273
274 switch(type) {
275 case(TS_ABSOLUTE_WITH_YMD):
276 case(TS_UTC_WITH_YMD):
277 switch(precision) {
278 case(TS_PREC_FIXED_SEC):
279 return "0000-00-00 00:00:00";
280 break;
281 case(TS_PREC_FIXED_DSEC):
282 return "0000-00-00 00:00:00.0";
283 break;
284 case(TS_PREC_FIXED_CSEC):
285 return "0000-00-00 00:00:00.00";
286 break;
287 case(TS_PREC_FIXED_MSEC):
288 return "0000-00-00 00:00:00.000";
289 break;
290 case(TS_PREC_FIXED_USEC):
291 return "0000-00-00 00:00:00.000000";
292 break;
293 case(TS_PREC_FIXED_NSEC):
294 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
295 return "0000-00-00 00:00:00.000000000";
296 break;
297 default:
298 ws_assert_not_reached();
299 }
300 break;
301 case(TS_ABSOLUTE_WITH_YDOY):
302 case(TS_UTC_WITH_YDOY):
303 switch(precision) {
304 case(TS_PREC_FIXED_SEC):
305 return "0000/000 00:00:00";
306 break;
307 case(TS_PREC_FIXED_DSEC):
308 return "0000/000 00:00:00.0";
309 break;
310 case(TS_PREC_FIXED_CSEC):
311 return "0000/000 00:00:00.00";
312 break;
313 case(TS_PREC_FIXED_MSEC):
314 return "0000/000 00:00:00.000";
315 break;
316 case(TS_PREC_FIXED_USEC):
317 return "0000/000 00:00:00.000000";
318 break;
319 case(TS_PREC_FIXED_NSEC):
320 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
321 return "0000/000 00:00:00.000000000";
322 break;
323 default:
324 ws_assert_not_reached();
325 }
326 break;
327 case(TS_ABSOLUTE):
328 case(TS_UTC):
329 switch(precision) {
330 case(TS_PREC_FIXED_SEC):
331 return "00:00:00";
332 break;
333 case(TS_PREC_FIXED_DSEC):
334 return "00:00:00.0";
335 break;
336 case(TS_PREC_FIXED_CSEC):
337 return "00:00:00.00";
338 break;
339 case(TS_PREC_FIXED_MSEC):
340 return "00:00:00.000";
341 break;
342 case(TS_PREC_FIXED_USEC):
343 return "00:00:00.000000";
344 break;
345 case(TS_PREC_FIXED_NSEC):
346 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
347 return "00:00:00.000000000";
348 break;
349 default:
350 ws_assert_not_reached();
351 }
352 break;
353 case(TS_RELATIVE): /* fallthrough */
354 case(TS_DELTA):
355 case(TS_DELTA_DIS):
356 switch(precision) {
357 case(TS_PREC_FIXED_SEC):
358 return "0000";
359 break;
360 case(TS_PREC_FIXED_DSEC):
361 return "0000.0";
362 break;
363 case(TS_PREC_FIXED_CSEC):
364 return "0000.00";
365 break;
366 case(TS_PREC_FIXED_MSEC):
367 return "0000.000";
368 break;
369 case(TS_PREC_FIXED_USEC):
370 return "0000.000000";
371 break;
372 case(TS_PREC_FIXED_NSEC):
373 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
374 return "0000.000000000";
375 break;
376 default:
377 ws_assert_not_reached();
378 }
379 break;
380 case(TS_EPOCH):
381 /* This is enough to represent 2^63 (signed 64-bit integer) + fractions */
382 switch(precision) {
383 case(TS_PREC_FIXED_SEC):
384 return "0000000000000000000";
385 break;
386 case(TS_PREC_FIXED_DSEC):
387 return "0000000000000000000.0";
388 break;
389 case(TS_PREC_FIXED_CSEC):
390 return "0000000000000000000.00";
391 break;
392 case(TS_PREC_FIXED_MSEC):
393 return "0000000000000000000.000";
394 break;
395 case(TS_PREC_FIXED_USEC):
396 return "0000000000000000000.000000";
397 break;
398 case(TS_PREC_FIXED_NSEC):
399 case(TS_PREC_AUTO): /* Leave enough room for the maximum */
400 return "0000000000000000000.000000000";
401 break;
402 default:
403 ws_assert_not_reached();
404 }
405 break;
406 case(TS_NOT_SET):
407 return "0000.000000";
408 break;
409 default:
410 ws_assert_not_reached();
411 }
412
413 /* never reached, satisfy compiler */
414 return "";
415 }
416
417 /* Returns a string representing the longest possible value for a
418 particular column type. See also get_column_width_string() above.
419
420 Except for the COL...SRC and COL...DST columns, these are used
421 only when a capture is being displayed while it's taking place;
422 they are arguably somewhat fragile, as changes to the code that
423 generates them don't cause these widths to change, but that's
424 probably not too big a problem, given that the sizes are
425 recomputed based on the actual data in the columns when the capture
426 is done, and given that the width for COL...SRC and COL...DST columns
427 is somewhat arbitrary in any case. We should probably clean
428 that up eventually, though. */
429 static const char *
get_column_longest_string(const gint format)430 get_column_longest_string(const gint format)
431 {
432 switch (format) {
433 case COL_NUMBER:
434 return "0000000";
435 break;
436 case COL_CLS_TIME:
437 return get_timestamp_column_longest_string(timestamp_get_type(), timestamp_get_precision());
438 break;
439 case COL_ABS_YMD_TIME:
440 return get_timestamp_column_longest_string(TS_ABSOLUTE_WITH_YMD, timestamp_get_precision());
441 break;
442 case COL_ABS_YDOY_TIME:
443 return get_timestamp_column_longest_string(TS_ABSOLUTE_WITH_YDOY, timestamp_get_precision());
444 break;
445 case COL_UTC_YMD_TIME:
446 return get_timestamp_column_longest_string(TS_UTC_WITH_YMD, timestamp_get_precision());
447 break;
448 case COL_UTC_YDOY_TIME:
449 return get_timestamp_column_longest_string(TS_UTC_WITH_YDOY, timestamp_get_precision());
450 break;
451 case COL_ABS_TIME:
452 return get_timestamp_column_longest_string(TS_ABSOLUTE, timestamp_get_precision());
453 break;
454 case COL_UTC_TIME:
455 return get_timestamp_column_longest_string(TS_UTC, timestamp_get_precision());
456 break;
457 case COL_REL_TIME:
458 return get_timestamp_column_longest_string(TS_RELATIVE, timestamp_get_precision());
459 break;
460 case COL_DELTA_TIME:
461 return get_timestamp_column_longest_string(TS_DELTA, timestamp_get_precision());
462 break;
463 case COL_DELTA_TIME_DIS:
464 return get_timestamp_column_longest_string(TS_DELTA_DIS, timestamp_get_precision());
465 break;
466 case COL_DEF_SRC:
467 case COL_RES_SRC:
468 case COL_UNRES_SRC:
469 case COL_DEF_DL_SRC:
470 case COL_RES_DL_SRC:
471 case COL_UNRES_DL_SRC:
472 case COL_DEF_NET_SRC:
473 case COL_RES_NET_SRC:
474 case COL_UNRES_NET_SRC:
475 case COL_DEF_DST:
476 case COL_RES_DST:
477 case COL_UNRES_DST:
478 case COL_DEF_DL_DST:
479 case COL_RES_DL_DST:
480 case COL_UNRES_DL_DST:
481 case COL_DEF_NET_DST:
482 case COL_RES_NET_DST:
483 case COL_UNRES_NET_DST:
484 return "00000000.000000000000"; /* IPX-style */
485 break;
486 case COL_DEF_SRC_PORT:
487 case COL_RES_SRC_PORT:
488 case COL_UNRES_SRC_PORT:
489 case COL_DEF_DST_PORT:
490 case COL_RES_DST_PORT:
491 case COL_UNRES_DST_PORT:
492 return "000000";
493 break;
494 case COL_PROTOCOL:
495 return "Protocol"; /* not the longest, but the longest is too long */
496 break;
497 case COL_PACKET_LENGTH:
498 return "00000";
499 break;
500 case COL_CUMULATIVE_BYTES:
501 return "00000000";
502 break;
503 case COL_IF_DIR:
504 return "i 00000000 I";
505 break;
506 case COL_VSAN:
507 return "000000";
508 break;
509 case COL_TX_RATE:
510 return "108.0";
511 break;
512 case COL_RSSI:
513 return "100";
514 break;
515 case COL_DCE_CALL:
516 return "0000";
517 break;
518 case COL_8021Q_VLAN_ID:
519 return "0000";
520 break;
521 case COL_DSCP_VALUE:
522 return "AAA BBB"; /* not the longest, but the longest is too long */
523 break;
524 case COL_TEI:
525 return "127";
526 break;
527 case COL_EXPERT:
528 return "ERROR";
529 break;
530 case COL_FREQ_CHAN:
531 return "9999 MHz [A 999]";
532 break;
533 case COL_CUSTOM:
534 return "0000000000"; /* not the longest, but the longest is too long */
535 break;
536 default: /* COL_INFO */
537 return "Source port: kerberos-master Destination port: kerberos-master";
538 break;
539 }
540 }
541
542 /* Returns the longer string of the column title or the hard-coded width of
543 * its contents for building the packet list layout. */
544 const gchar *
get_column_width_string(const gint format,const gint col)545 get_column_width_string(const gint format, const gint col)
546 {
547 if(strlen(get_column_longest_string(format)) >
548 strlen(get_column_title(col)))
549 return get_column_longest_string(format);
550 else
551 return get_column_title(col);
552 }
553
554 /* Returns the longest possible width, in characters, for a particular
555 column type. */
556 gint
get_column_char_width(const gint format)557 get_column_char_width(const gint format)
558 {
559 return (gint)strlen(get_column_longest_string(format));
560 }
561
562 gint
get_column_format(const gint col)563 get_column_format(const gint col)
564 {
565 GList *clp = g_list_nth(prefs.col_list, col);
566 fmt_data *cfmt;
567
568 if (!clp) /* Invalid column requested */
569 return -1;
570
571 cfmt = (fmt_data *) clp->data;
572
573 return(cfmt->fmt);
574 }
575
576 void
set_column_format(const gint col,const gint fmt)577 set_column_format(const gint col, const gint fmt)
578 {
579 GList *clp = g_list_nth(prefs.col_list, col);
580 fmt_data *cfmt;
581
582 if (!clp) /* Invalid column requested */
583 return;
584
585 cfmt = (fmt_data *) clp->data;
586
587 cfmt->fmt = fmt;
588 }
589
590 gint
get_column_format_from_str(const gchar * str)591 get_column_format_from_str(const gchar *str)
592 {
593 gint i;
594
595 for (i = 0; i < NUM_COL_FMTS; i++) {
596 if (strcmp(str, col_format_to_string(i)) == 0)
597 return i;
598 }
599 return -1; /* illegal */
600 }
601
602 gchar *
get_column_title(const gint col)603 get_column_title(const gint col)
604 {
605 GList *clp = g_list_nth(prefs.col_list, col);
606 fmt_data *cfmt;
607
608 if (!clp) /* Invalid column requested */
609 return NULL;
610
611 cfmt = (fmt_data *) clp->data;
612
613 return(cfmt->title);
614 }
615
616 void
set_column_title(const gint col,const gchar * title)617 set_column_title(const gint col, const gchar *title)
618 {
619 GList *clp = g_list_nth(prefs.col_list, col);
620 fmt_data *cfmt;
621
622 if (!clp) /* Invalid column requested */
623 return;
624
625 cfmt = (fmt_data *) clp->data;
626
627 g_free (cfmt->title);
628 cfmt->title = g_strdup (title);
629 }
630
631 gboolean
get_column_visible(const gint col)632 get_column_visible(const gint col)
633 {
634 GList *clp = g_list_nth(prefs.col_list, col);
635 fmt_data *cfmt;
636
637 if (!clp) /* Invalid column requested */
638 return TRUE;
639
640 cfmt = (fmt_data *) clp->data;
641
642 return(cfmt->visible);
643 }
644
645 void
set_column_visible(const gint col,gboolean visible)646 set_column_visible(const gint col, gboolean visible)
647 {
648 GList *clp = g_list_nth(prefs.col_list, col);
649 fmt_data *cfmt;
650
651 if (!clp) /* Invalid column requested */
652 return;
653
654 cfmt = (fmt_data *) clp->data;
655
656 cfmt->visible = visible;
657 }
658
659 gboolean
get_column_resolved(const gint col)660 get_column_resolved(const gint col)
661 {
662 GList *clp = g_list_nth(prefs.col_list, col);
663 fmt_data *cfmt;
664
665 if (!clp) /* Invalid column requested */
666 return TRUE;
667
668 cfmt = (fmt_data *) clp->data;
669
670 return(cfmt->resolved);
671 }
672
673 void
set_column_resolved(const gint col,gboolean resolved)674 set_column_resolved(const gint col, gboolean resolved)
675 {
676 GList *clp = g_list_nth(prefs.col_list, col);
677 fmt_data *cfmt;
678
679 if (!clp) /* Invalid column requested */
680 return;
681
682 cfmt = (fmt_data *) clp->data;
683
684 cfmt->resolved = resolved;
685 }
686
687 const gchar *
get_column_custom_fields(const gint col)688 get_column_custom_fields(const gint col)
689 {
690 GList *clp = g_list_nth(prefs.col_list, col);
691 fmt_data *cfmt;
692
693 if (!clp) /* Invalid column requested */
694 return NULL;
695
696 cfmt = (fmt_data *) clp->data;
697
698 return(cfmt->custom_fields);
699 }
700
701 void
set_column_custom_fields(const gint col,const char * custom_fields)702 set_column_custom_fields(const gint col, const char *custom_fields)
703 {
704 GList *clp = g_list_nth(prefs.col_list, col);
705 fmt_data *cfmt;
706
707 if (!clp) /* Invalid column requested */
708 return;
709
710 cfmt = (fmt_data *) clp->data;
711
712 g_free (cfmt->custom_fields);
713 cfmt->custom_fields = g_strdup (custom_fields);
714 }
715
716 gint
get_column_custom_occurrence(const gint col)717 get_column_custom_occurrence(const gint col)
718 {
719 GList *clp = g_list_nth(prefs.col_list, col);
720 fmt_data *cfmt;
721
722 if (!clp) /* Invalid column requested */
723 return 0;
724
725 cfmt = (fmt_data *) clp->data;
726
727 return(cfmt->custom_occurrence);
728 }
729
730 void
set_column_custom_occurrence(const gint col,const gint custom_occurrence)731 set_column_custom_occurrence(const gint col, const gint custom_occurrence)
732 {
733 GList *clp = g_list_nth(prefs.col_list, col);
734 fmt_data *cfmt;
735
736 if (!clp) /* Invalid column requested */
737 return;
738
739 cfmt = (fmt_data *) clp->data;
740
741 cfmt->custom_occurrence = custom_occurrence;
742 }
743
744 static gchar *
get_custom_field_tooltip(gchar * custom_field,gint occurrence)745 get_custom_field_tooltip (gchar *custom_field, gint occurrence)
746 {
747 header_field_info *hfi = proto_registrar_get_byname(custom_field);
748 if (hfi == NULL) {
749 /* Not a valid field */
750 return g_strdup_printf("Unknown Field: %s", custom_field);
751 }
752
753 if (hfi->parent == -1) {
754 /* Protocol */
755 return g_strdup_printf("%s (%s)", hfi->name, hfi->abbrev);
756 }
757
758 if (occurrence == 0) {
759 /* All occurrences */
760 return g_strdup_printf("%s\n%s (%s)", proto_get_protocol_name(hfi->parent), hfi->name, hfi->abbrev);
761 }
762
763 /* One given occurrence */
764 return g_strdup_printf("%s\n%s (%s#%d)", proto_get_protocol_name(hfi->parent), hfi->name, hfi->abbrev, occurrence);
765 }
766
767 gchar *
get_column_tooltip(const gint col)768 get_column_tooltip(const gint col)
769 {
770 GList *clp = g_list_nth(prefs.col_list, col);
771 fmt_data *cfmt;
772 gchar **fields;
773 gboolean first = TRUE;
774 GString *column_tooltip;
775 guint i;
776
777 if (!clp) /* Invalid column requested */
778 return NULL;
779
780 cfmt = (fmt_data *) clp->data;
781
782 if (cfmt->fmt != COL_CUSTOM) {
783 /* Use format description */
784 return g_strdup(col_format_desc(cfmt->fmt));
785 }
786
787 fields = g_regex_split_simple(COL_CUSTOM_PRIME_REGEX, cfmt->custom_fields,
788 (GRegexCompileFlags) (G_REGEX_ANCHORED | G_REGEX_RAW),
789 G_REGEX_MATCH_ANCHORED);
790 column_tooltip = g_string_new("");
791
792 for (i = 0; i < g_strv_length(fields); i++) {
793 if (fields[i] && *fields[i]) {
794 gchar *field_tooltip = get_custom_field_tooltip(fields[i], cfmt->custom_occurrence);
795 if (!first) {
796 g_string_append(column_tooltip, "\n\nOR\n\n");
797 }
798 g_string_append(column_tooltip, field_tooltip);
799 g_free (field_tooltip);
800 first = FALSE;
801 }
802 }
803
804 g_strfreev(fields);
805
806 return g_string_free (column_tooltip, FALSE);
807 }
808
809 void
col_finalize(column_info * cinfo)810 col_finalize(column_info *cinfo)
811 {
812 int i;
813 col_item_t* col_item;
814
815 for (i = 0; i < cinfo->num_cols; i++) {
816 col_item = &cinfo->columns[i];
817
818 if (col_item->col_fmt == COL_CUSTOM) {
819 if(!dfilter_compile(col_item->col_custom_fields, &col_item->col_custom_dfilter, NULL)) {
820 /* XXX: Should we issue a warning? */
821 g_free(col_item->col_custom_fields);
822 col_item->col_custom_fields = NULL;
823 col_item->col_custom_occurrence = 0;
824 col_item->col_custom_dfilter = NULL;
825 }
826 if (col_item->col_custom_fields) {
827 gchar **fields = g_regex_split(cinfo->prime_regex, col_item->col_custom_fields,
828 G_REGEX_MATCH_ANCHORED);
829 guint i_field;
830
831 for (i_field = 0; i_field < g_strv_length(fields); i_field++) {
832 if (fields[i_field] && *fields[i_field]) {
833 header_field_info *hfinfo = proto_registrar_get_byname(fields[i_field]);
834 if (hfinfo) {
835 int *idx = g_new(int, 1);
836 *idx = hfinfo->id;
837 col_item->col_custom_fields_ids = g_slist_append(col_item->col_custom_fields_ids, idx);
838 }
839 }
840 }
841 g_strfreev(fields);
842 }
843 } else {
844 col_item->col_custom_fields = NULL;
845 col_item->col_custom_occurrence = 0;
846 col_item->col_custom_dfilter = NULL;
847 }
848
849 col_item->fmt_matx = g_new0(gboolean, NUM_COL_FMTS);
850 get_column_format_matches(col_item->fmt_matx, col_item->col_fmt);
851 col_item->col_data = NULL;
852
853 if (col_item->col_fmt == COL_INFO)
854 col_item->col_buf = g_new(gchar, COL_MAX_INFO_LEN);
855 else
856 col_item->col_buf = g_new(gchar, COL_MAX_LEN);
857
858 cinfo->col_expr.col_expr[i] = "";
859 cinfo->col_expr.col_expr_val[i] = g_new(gchar, COL_MAX_LEN);
860 }
861
862 cinfo->col_expr.col_expr[i] = NULL;
863 cinfo->col_expr.col_expr_val[i] = NULL;
864
865 for (i = 0; i < cinfo->num_cols; i++) {
866 int j;
867
868 for (j = 0; j < NUM_COL_FMTS; j++) {
869 if (!cinfo->columns[i].fmt_matx[j])
870 continue;
871
872 if (cinfo->col_first[j] == -1)
873 cinfo->col_first[j] = i;
874
875 cinfo->col_last[j] = i;
876 }
877 }
878 }
879
880 void
build_column_format_array(column_info * cinfo,const gint num_cols,const gboolean reset_fences)881 build_column_format_array(column_info *cinfo, const gint num_cols, const gboolean reset_fences)
882 {
883 int i;
884 col_item_t* col_item;
885
886 /* Build the column format array */
887 col_setup(cinfo, num_cols);
888
889 for (i = 0; i < cinfo->num_cols; i++) {
890 col_item = &cinfo->columns[i];
891 col_item->col_fmt = get_column_format(i);
892 col_item->col_title = g_strdup(get_column_title(i));
893 if (col_item->col_fmt == COL_CUSTOM) {
894 col_item->col_custom_fields = g_strdup(get_column_custom_fields(i));
895 col_item->col_custom_occurrence = get_column_custom_occurrence(i);
896 }
897
898 if(reset_fences)
899 col_item->col_fence = 0;
900 }
901
902 col_finalize(cinfo);
903 }
904
905 /*
906 * Editor modelines - https://www.wireshark.org/tools/modelines.html
907 *
908 * Local variables:
909 * c-basic-offset: 2
910 * tab-width: 8
911 * indent-tabs-mode: nil
912 * End:
913 *
914 * vi: set shiftwidth=2 tabstop=8 expandtab:
915 * :indentSize=2:tabSize=8:noTabs=true:
916 */
917
918