-B is no longer Windows-only.
[obnox/wireshark/wip.git] / file.c
1 /* file.c
2  * File I/O routines
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #include <time.h>
34
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <errno.h>
40 #include <signal.h>
41
42 #ifdef HAVE_FCNTL_H
43 #include <fcntl.h>
44 #endif
45
46 #include <epan/epan.h>
47 #include <epan/filesystem.h>
48
49 #include "color.h"
50 #include "color_filters.h"
51 #include "cfile.h"
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include "packet-range.h"
56 #include "print.h"
57 #include "file.h"
58 #include "fileset.h"
59 #include "tempfile.h"
60 #include "merge.h"
61 #include "alert_box.h"
62 #include "simple_dialog.h"
63 #include "progress_dlg.h"
64 #include "ui_util.h"
65 #include <epan/prefs.h>
66 #include <epan/dfilter/dfilter.h>
67 #include <epan/epan_dissect.h>
68 #include <epan/tap.h>
69 #include <epan/dissectors/packet-data.h>
70 #include <epan/dissectors/packet-ber.h>
71 #include <epan/timestamp.h>
72 #include <epan/dfilter/dfilter-macro.h>
73 #include <wsutil/file_util.h>
74 #include <epan/strutil.h>
75
76 #ifdef HAVE_LIBPCAP
77 gboolean auto_scroll_live;
78 #endif
79
80 static guint32 cum_bytes;
81 static nstime_t first_ts;
82 static nstime_t prev_dis_ts;
83 static nstime_t prev_cap_ts;
84
85 static gulong computed_elapsed;
86
87 static void cf_reset_state(capture_file *cf);
88
89 static int read_packet(capture_file *cf, dfilter_t *dfcode,
90     gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
91
92 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
93     gboolean refilter, gboolean redissect);
94
95 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
96     void *criterion);
97 static void match_subtree_text(proto_node *node, gpointer data);
98 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
99     void *criterion);
100 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
101     void *criterion);
102 static gboolean match_ascii(capture_file *cf, frame_data *fdata,
103     void *criterion);
104 static gboolean match_unicode(capture_file *cf, frame_data *fdata,
105     void *criterion);
106 static gboolean match_binary(capture_file *cf, frame_data *fdata,
107     void *criterion);
108 static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
109     void *criterion);
110 static gboolean find_packet(capture_file *cf,
111     gboolean (*match_function)(capture_file *, frame_data *, void *),
112     void *criterion);
113
114 static void cf_open_failure_alert_box(const char *filename, int err,
115                       gchar *err_info, gboolean for_writing,
116                       int file_type);
117 static const char *file_rename_error_message(int err);
118 static void cf_write_failure_alert_box(const char *filename, int err);
119 static void cf_close_failure_alert_box(const char *filename, int err);
120 #ifdef NEW_PACKET_LIST
121 static void ref_time_packets(capture_file *cf);
122 #endif
123 /* Update the progress bar this many times when reading a file. */
124 #define N_PROGBAR_UPDATES   100
125 /* We read around 200k/100ms don't update the progress bar more often than that */
126 #define MIN_QUANTUM         200000
127 #define MIN_NUMBER_OF_PACKET 1500
128
129 /* Number of "frame_data" structures per memory chunk.
130    XXX - is this the right number? */
131 #define FRAME_DATA_CHUNK_SIZE   1024
132
133
134 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
135 typedef struct {
136   cf_callback_t cb_fct;
137   gpointer user_data;
138 } cf_callback_data_t;
139
140 static GList *cf_callbacks = NULL;
141
142 static void
143 cf_callback_invoke(int event, gpointer data)
144 {
145   cf_callback_data_t *cb;
146   GList *cb_item = cf_callbacks;
147
148   /* there should be at least one interested */
149   g_assert(cb_item != NULL);
150
151   while(cb_item != NULL) {
152     cb = cb_item->data;
153     cb->cb_fct(event, data, cb->user_data);
154     cb_item = g_list_next(cb_item);
155   }
156 }
157
158
159 void
160 cf_callback_add(cf_callback_t func, gpointer user_data)
161 {
162   cf_callback_data_t *cb;
163
164   cb = g_malloc(sizeof(cf_callback_data_t));
165   cb->cb_fct = func;
166   cb->user_data = user_data;
167
168   cf_callbacks = g_list_append(cf_callbacks, cb);
169 }
170
171 void
172 cf_callback_remove(cf_callback_t func)
173 {
174   cf_callback_data_t *cb;
175   GList *cb_item = cf_callbacks;
176
177   while(cb_item != NULL) {
178     cb = cb_item->data;
179     if(cb->cb_fct == func) {
180       cf_callbacks = g_list_remove(cf_callbacks, cb);
181       g_free(cb);
182       return;
183     }
184     cb_item = g_list_next(cb_item);
185   }
186
187   g_assert_not_reached();
188 }
189
190 void
191 cf_timestamp_auto_precision(capture_file *cf)
192 {
193 #ifdef NEW_PACKET_LIST
194   int i;
195 #endif
196   int prec = timestamp_get_precision();
197
198
199   /* don't try to get the file's precision if none is opened */
200   if(cf->state == FILE_CLOSED) {
201     return;
202   }
203
204   /* if we are in auto mode, set precision of current file */
205   if(prec == TS_PREC_AUTO ||
206      prec == TS_PREC_AUTO_SEC ||
207      prec == TS_PREC_AUTO_DSEC ||
208      prec == TS_PREC_AUTO_CSEC ||
209      prec == TS_PREC_AUTO_MSEC ||
210      prec == TS_PREC_AUTO_USEC ||
211      prec == TS_PREC_AUTO_NSEC)
212   {
213     switch(wtap_file_tsprecision(cf->wth)) {
214     case(WTAP_FILE_TSPREC_SEC):
215       timestamp_set_precision(TS_PREC_AUTO_SEC);
216       break;
217     case(WTAP_FILE_TSPREC_DSEC):
218       timestamp_set_precision(TS_PREC_AUTO_DSEC);
219       break;
220     case(WTAP_FILE_TSPREC_CSEC):
221       timestamp_set_precision(TS_PREC_AUTO_CSEC);
222       break;
223     case(WTAP_FILE_TSPREC_MSEC):
224       timestamp_set_precision(TS_PREC_AUTO_MSEC);
225       break;
226     case(WTAP_FILE_TSPREC_USEC):
227       timestamp_set_precision(TS_PREC_AUTO_USEC);
228       break;
229     case(WTAP_FILE_TSPREC_NSEC):
230       timestamp_set_precision(TS_PREC_AUTO_NSEC);
231       break;
232     default:
233       g_assert_not_reached();
234     }
235   }
236 #ifdef NEW_PACKET_LIST
237   /* Set the column widths of those columns that show the time in
238      "command-line-specified" format. */
239   for (i = 0; i < cf->cinfo.num_cols; i++) {
240     if (col_has_time_fmt(&cf->cinfo, i)) {
241       new_packet_list_resize_column(i);
242     }
243   }
244 #endif
245 }
246
247 gulong
248 cf_get_computed_elapsed(void)
249 {
250   return computed_elapsed;
251 }
252
253 static void reset_elapsed(void)
254 {
255   computed_elapsed = 0;
256 }
257
258 static void compute_elapsed(GTimeVal *start_time)
259 {
260   gdouble    delta_time;
261   GTimeVal   time_now;
262
263   g_get_current_time(&time_now);
264
265   delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
266     time_now.tv_usec - start_time->tv_usec;
267
268   computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
269 }
270
271 cf_status_t
272 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
273 {
274   wtap       *wth;
275   gchar       *err_info;
276
277   wth = wtap_open_offline(fname, err, &err_info, TRUE);
278   if (wth == NULL)
279     goto fail;
280
281   /* The open succeeded.  Close whatever capture file we had open,
282      and fill in the information for this file. */
283   cf_reset_state(cf);
284
285   /* Cleanup all data structures used for dissection. */
286   cleanup_dissection();
287   /* Initialize all data structures used for dissection. */
288   init_dissection();
289
290   /* We're about to start reading the file. */
291   cf->state = FILE_READ_IN_PROGRESS;
292
293   cf->wth = wth;
294   cf->f_datalen = 0;
295
296   /* Set the file name because we need it to set the follow stream filter.
297      XXX - is that still true?  We need it for other reasons, though,
298      in any case. */
299   cf->filename = g_strdup(fname);
300
301   /* Indicate whether it's a permanent or temporary file. */
302   cf->is_tempfile = is_tempfile;
303
304   /* If it's a temporary capture buffer file, mark it as not saved. */
305   cf->user_saved = !is_tempfile;
306
307   reset_elapsed();
308
309   cf->cd_t        = wtap_file_type(cf->wth);
310   cf->count     = 0;
311   cf->displayed_count = 0;
312   cf->marked_count = 0;
313   cf->ignored_count = 0;
314   cf->drops_known = FALSE;
315   cf->drops     = 0;
316   cf->snap      = wtap_snapshot_length(cf->wth);
317   if (cf->snap == 0) {
318     /* Snapshot length not known. */
319     cf->has_snap = FALSE;
320     cf->snap = WTAP_MAX_PACKET_SIZE;
321   } else
322     cf->has_snap = TRUE;
323
324   nstime_set_zero(&cf->elapsed_time);
325   nstime_set_unset(&first_ts);
326   nstime_set_unset(&prev_dis_ts);
327   nstime_set_unset(&prev_cap_ts);
328   cum_bytes = 0;
329
330 #if GLIB_CHECK_VERSION(2,10,0)
331 #else
332   /* memory chunks have been deprecated in favor of the slice allocator,
333    * which has been added in 2.10
334    */
335   cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
336     sizeof(frame_data),
337     FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
338     G_ALLOC_AND_FREE);
339   g_assert(cf->plist_chunk);
340 #endif
341
342 #ifdef NEW_PACKET_LIST
343   /* Adjust timestamp precision if auto is selected, col width will be adjusted */
344   cf_timestamp_auto_precision(cf);
345   /* XXX needed ? */
346   new_packet_list_queue_draw();
347 #else
348   /* change the time formats now, as we might have a new precision */
349   cf_change_time_formats(cf);
350 #endif
351   fileset_file_opened(fname);
352
353   if(cf->cd_t == WTAP_FILE_BER) {
354     /* tell the BER dissector the file name */
355     ber_set_filename(cf->filename);
356   }
357
358   return CF_OK;
359
360 fail:
361   cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
362   return CF_ERROR;
363 }
364
365
366 /*
367  * Reset the state for the currently closed file, but don't do the
368  * UI callbacks; this is for use in "cf_open()", where we don't
369  * want the UI to go from "file open" to "file closed" back to
370  * "file open", we want it to go from "old file open" to "new file
371  * open and being read".
372  */
373 static void
374 cf_reset_state(capture_file *cf)
375 {
376   /* Die if we're in the middle of reading a file. */
377   g_assert(cf->state != FILE_READ_IN_PROGRESS);
378
379   if (cf->wth) {
380     wtap_close(cf->wth);
381     cf->wth = NULL;
382   }
383   /* We have no file open... */
384   if (cf->filename != NULL) {
385     /* If it's a temporary file, remove it. */
386     if (cf->is_tempfile)
387       ws_unlink(cf->filename);
388     g_free(cf->filename);
389     cf->filename = NULL;
390   }
391   /* ...which means we have nothing to save. */
392   cf->user_saved = FALSE;
393
394 #if GLIB_CHECK_VERSION(2,10,0)
395   if (cf->plist_start != NULL)
396     g_slice_free_chain(frame_data, cf->plist_start, next);
397 #else
398   /* memory chunks have been deprecated in favor of the slice allocator,
399    * which has been added in 2.10
400    */
401   if (cf->plist_chunk != NULL) {
402     g_mem_chunk_destroy(cf->plist_chunk);
403     cf->plist_chunk = NULL;
404   }
405 #endif
406   dfilter_free(cf->rfcode);
407   cf->rfcode = NULL;
408   cf->plist_start = NULL;
409   cf->plist_end = NULL;
410   cf_unselect_packet(cf);   /* nothing to select */
411   cf->first_displayed = NULL;
412   cf->last_displayed = NULL;
413
414   /* No frame selected, no field in that frame selected. */
415   cf->current_frame = NULL;
416   cf->current_row = 0;
417   cf->finfo_selected = NULL;
418
419   /* Clear the packet list. */
420 #ifdef NEW_PACKET_LIST
421   new_packet_list_freeze();
422   new_packet_list_clear();
423   new_packet_list_thaw();
424 #else
425   packet_list_freeze();
426   packet_list_clear();
427   packet_list_thaw();
428 #endif
429
430   cf->f_datalen = 0;
431   cf->count = 0;
432   nstime_set_zero(&cf->elapsed_time);
433
434   reset_tap_listeners();
435
436   /* We have no file open. */
437   cf->state = FILE_CLOSED;
438
439   fileset_file_closed();
440 }
441
442 /* Reset everything to a pristine state */
443 void
444 cf_close(capture_file *cf)
445 {
446   /* do GUI things even if file is already closed,
447    * e.g. to cleanup things if a capture couldn't be started */
448   cf_callback_invoke(cf_cb_file_closing, cf);
449
450   /* close things, if not already closed before */
451   if(cf->state != FILE_CLOSED) {
452     color_filters_cleanup();
453     cf_reset_state(cf);
454     cleanup_dissection();
455   }
456
457   cf_callback_invoke(cf_cb_file_closed, cf);
458 }
459
460 /* an out of memory exception occured, wait for a user button press to exit */
461 static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
462 {
463     main_window_exit();
464 }
465
466 static float calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos){
467
468   float   progbar_val;
469
470   progbar_val = (gfloat) file_pos / (gfloat) size;
471   if (progbar_val > 1.0) {
472     /* The file probably grew while we were reading it.
473        Update file size, and try again. */
474     size = wtap_file_size(cf->wth, NULL);
475     if (size >= 0)
476       progbar_val = (gfloat) file_pos / (gfloat) size;
477     /* If it's still > 1, either "wtap_file_size()" failed (in which
478        case there's not much we can do about it), or the file
479        *shrank* (in which case there's not much we can do about
480        it); just clip the progress value at 1.0. */
481     if (progbar_val > 1.0f)
482       progbar_val = 1.0f;
483   }
484   return progbar_val;
485 }
486
487 cf_read_status_t
488 cf_read(capture_file *cf, gboolean from_save)
489 {
490   int         err;
491   gchar       *err_info;
492   const gchar *name_ptr;
493   const char  *errmsg;
494   char         errmsg_errno[1024+1];
495   gint64       data_offset;
496   progdlg_t *volatile progbar = NULL;
497   gboolean     stop_flag;
498   volatile gint64 size;
499   volatile float progbar_val;
500   GTimeVal     start_time;
501   gchar        status_str[100];
502   volatile gint64 progbar_nextstep;
503   volatile gint64 progbar_quantum;
504   dfilter_t   *dfcode;
505   gboolean    filtering_tap_listeners;
506   guint       tap_flags;
507   volatile int count = 0;
508 #ifdef HAVE_LIBPCAP
509   volatile int displayed_once = 0;
510 #endif
511   gboolean compiled;
512
513   /* Compile the current display filter.
514    * We assume this will not fail since cf->dfilter is only set in
515    * cf_filter IFF the filter was valid.
516    */
517   compiled = dfilter_compile(cf->dfilter, &dfcode);
518   g_assert(!cf->dfilter || (compiled && dfcode));
519
520   /* Do we have any tap listeners with filters? */
521   filtering_tap_listeners = have_filtering_tap_listeners();
522
523   /* Get the union of the flags for all tap listeners. */
524   tap_flags = union_of_tap_listener_flags();
525
526   reset_tap_listeners();
527
528   name_ptr = get_basename(cf->filename);
529
530   if (from_save == FALSE)
531     cf_callback_invoke(cf_cb_file_read_started, cf);
532   else
533     cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
534
535   /* Find the size of the file. */
536   size = wtap_file_size(cf->wth, NULL);
537
538   /* Update the progress bar when it gets to this value. */
539   progbar_nextstep = 0;
540   /* When we reach the value that triggers a progress bar update,
541      bump that value by this amount. */
542   if (size >= 0){
543     progbar_quantum = size/N_PROGBAR_UPDATES;
544     if (progbar_quantum < MIN_QUANTUM)
545       progbar_quantum = MIN_QUANTUM;
546   }else
547     progbar_quantum = 0;
548   /* Progress so far. */
549   progbar_val = 0.0f;
550
551 #ifdef NEW_PACKET_LIST
552   new_packet_list_freeze();
553 #else
554   packet_list_freeze();
555 #endif
556
557   stop_flag = FALSE;
558   g_get_current_time(&start_time);
559
560   while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
561     if (size >= 0) {
562       count++;
563       /* Create the progress bar if necessary.
564        * Check wether it should be created or not every MIN_NUMBER_OF_PACKET
565        */
566       if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
567         progbar_val = calc_progbar_val( cf, size, data_offset);
568         if (from_save == FALSE)
569           progbar = delayed_create_progress_dlg("Loading", name_ptr,
570                                                 TRUE, &stop_flag, &start_time, progbar_val);
571         else
572           progbar = delayed_create_progress_dlg("Saving", name_ptr,
573                                                 TRUE, &stop_flag, &start_time, progbar_val);
574       }
575
576       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
577          when we update it, we have to run the GTK+ main loop to get it
578          to repaint what's pending, and doing so may involve an "ioctl()"
579          to see if there's any pending input from an X server, and doing
580          that for every packet can be costly, especially on a big file. */
581       if (data_offset >= progbar_nextstep) {
582         if (progbar != NULL) {
583           progbar_val = calc_progbar_val( cf, size, data_offset);
584           /* update the packet lists content on the first run or frequently on very large files */
585           /* (on smaller files the display update takes longer than reading the file) */
586 #ifdef HAVE_LIBPCAP
587           if (progbar_quantum > 500000 || displayed_once == 0) {
588             if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
589               displayed_once = 1;
590 #ifdef NEW_PACKET_LIST
591               new_packet_list_thaw();
592               if (auto_scroll_live)
593                 new_packet_list_moveto_end();
594               new_packet_list_freeze();
595 #else
596               packet_list_thaw();
597               if (auto_scroll_live)
598                 packet_list_moveto_end();
599               packet_list_freeze();
600 #endif /* NEW_PACKET_LIST */
601             }
602           }
603 #endif /* HAVE_LIBPCAP */
604           g_snprintf(status_str, sizeof(status_str),
605                      "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
606                      data_offset / 1024, size / 1024);
607           update_progress_dlg(progbar, progbar_val, status_str);
608         }
609         progbar_nextstep += progbar_quantum;
610       }
611     }
612
613     if (stop_flag) {
614       /* Well, the user decided to abort the read. He/She will be warned and
615          it might be enough for him/her to work with the already loaded
616          packets.
617          This is especially true for very large capture files, where you don't
618          want to wait loading the whole file (which may last minutes or even
619          hours even on fast machines) just to see that it was the wrong file. */
620       break;
621     }
622     TRY {
623       read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
624     }
625     CATCH(OutOfMemoryError) {
626       gpointer dialog;
627
628       dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
629                              "%sOut Of Memory!%s\n"
630                              "\n"
631                              "Sorry, but Wireshark has to terminate now!\n"
632                              "\n"
633                              "Some infos / workarounds can be found at:\n"
634                              "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
635                              simple_dialog_primary_start(), simple_dialog_primary_end());
636       /* we have to terminate, as we cannot recover from the memory error */
637       simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
638       while(1) {
639         main_window_update();
640         /* XXX - how to avoid a busy wait? */
641         /* Sleep(100); */
642       };
643       break;
644     }
645     ENDTRY;
646   }
647
648   /* Cleanup and release all dfilter resources */
649   if (dfcode != NULL){
650     dfilter_free(dfcode);
651   }
652
653   /* We're done reading the file; destroy the progress bar if it was created. */
654   if (progbar != NULL)
655     destroy_progress_dlg(progbar);
656
657   /* We're done reading sequentially through the file. */
658   cf->state = FILE_READ_DONE;
659
660   /* Close the sequential I/O side, to free up memory it requires. */
661   wtap_sequential_close(cf->wth);
662
663   /* Allow the protocol dissectors to free up memory that they
664    * don't need after the sequential run-through of the packets. */
665   postseq_cleanup_all_protocols();
666
667   /* compute the time it took to load the file */
668   compute_elapsed(&start_time);
669
670   /* Set the file encapsulation type now; we don't know what it is until
671      we've looked at all the packets, as we don't know until then whether
672      there's more than one type (and thus whether it's
673      WTAP_ENCAP_PER_PACKET). */
674   cf->lnk_t = wtap_file_encap(cf->wth);
675
676   cf->current_frame = cf->first_displayed;
677   cf->current_row = 0;
678
679 #ifdef NEW_PACKET_LIST
680   new_packet_list_thaw();
681 #else
682   packet_list_thaw();
683 #endif
684   if (from_save == FALSE)
685     cf_callback_invoke(cf_cb_file_read_finished, cf);
686   else
687     cf_callback_invoke(cf_cb_file_save_finished, cf);
688
689   /* If we have any displayed packets to select, select the first of those
690      packets by making the first row the selected row. */
691   if (cf->first_displayed != NULL){
692 #ifdef NEW_PACKET_LIST
693     new_packet_list_select_first_row();
694 #else
695     packet_list_select_row(0);
696 #endif /* NEW_PACKET_LIST */
697   }
698
699   if(stop_flag) {
700     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
701                   "%sFile loading was cancelled!%s\n"
702                   "\n"
703                   "The remaining packets in the file were discarded.\n"
704                   "\n"
705                   "As a lot of packets from the original file will be missing,\n"
706                   "remember to be careful when saving the current content to a file.\n",
707                   simple_dialog_primary_start(), simple_dialog_primary_end());
708     return CF_READ_ERROR;
709   }
710
711   if (err != 0) {
712     /* Put up a message box noting that the read failed somewhere along
713        the line.  Don't throw out the stuff we managed to read, though,
714        if any. */
715     switch (err) {
716
717     case WTAP_ERR_UNSUPPORTED_ENCAP:
718       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
719                  "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
720                  err_info);
721       g_free(err_info);
722       errmsg = errmsg_errno;
723       break;
724
725     case WTAP_ERR_CANT_READ:
726       errmsg = "An attempt to read from the capture file failed for"
727         " some unknown reason.";
728       break;
729
730     case WTAP_ERR_SHORT_READ:
731       errmsg = "The capture file appears to have been cut short"
732         " in the middle of a packet.";
733       break;
734
735     case WTAP_ERR_BAD_RECORD:
736       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
737                  "The capture file appears to be damaged or corrupt.\n(%s)",
738                  err_info);
739       g_free(err_info);
740       errmsg = errmsg_errno;
741       break;
742
743     default:
744       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
745                  "An error occurred while reading the"
746                  " capture file: %s.", wtap_strerror(err));
747       errmsg = errmsg_errno;
748       break;
749     }
750     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
751     return CF_READ_ERROR;
752   } else
753     return CF_READ_OK;
754 }
755
756 #ifdef HAVE_LIBPCAP
757 cf_status_t
758 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
759 {
760   cf_status_t cf_status;
761
762   cf_status = cf_open(cf, fname, is_tempfile, err);
763   return cf_status;
764 }
765
766 cf_read_status_t
767 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
768 {
769   gint64 data_offset = 0;
770   gchar *err_info;
771   volatile int newly_displayed_packets = 0;
772   dfilter_t   *dfcode;
773   gboolean filtering_tap_listeners;
774   guint tap_flags;
775   volatile gboolean visible = FALSE;
776   gboolean compiled;
777
778   /* Compile the current display filter.
779    * We assume this will not fail since cf->dfilter is only set in
780    * cf_filter IFF the filter was valid.
781    */
782   compiled = dfilter_compile(cf->dfilter, &dfcode);
783   g_assert(!cf->dfilter || (compiled && dfcode));
784
785   /* Do we have any tap listeners with filters? */
786   filtering_tap_listeners = have_filtering_tap_listeners();
787
788   /* Get the union of the flags for all tap listeners. */
789   tap_flags = union_of_tap_listener_flags();
790
791   *err = 0;
792
793 #ifdef NEW_PACKET_LIST
794   new_packet_list_check_end();
795   /* Don't freeze/thaw the list when doing live capture */
796   /*new_packet_list_freeze();*/
797 #else
798   packet_list_check_end();
799   packet_list_freeze();
800 #endif
801
802   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
803
804   while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
805     if (cf->state == FILE_READ_ABORTED) {
806       /* Well, the user decided to exit Wireshark.  Break out of the
807          loop, and let the code below (which is called even if there
808          aren't any packets left to read) exit. */
809       break;
810     }
811     TRY{
812       if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
813                       data_offset) != -1) {
814         visible = TRUE;
815         newly_displayed_packets++;
816       }else{
817         visible = FALSE;
818       }
819     }
820     CATCH(OutOfMemoryError) {
821       gpointer dialog;
822
823       dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
824                              "%sOut Of Memory!%s\n"
825                              "\n"
826                              "Sorry, but Wireshark has to terminate now!\n"
827                              "\n"
828                              "The capture file is not lost, it can be found at:\n"
829                              "%s\n"
830                              "\n"
831                              "Some infos / workarounds can be found at:\n"
832                              "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
833                              simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
834       /* we have to terminate, as we cannot recover from the memory error */
835       simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
836       while(1) {
837         main_window_update();
838         /* XXX - how to avoid a busy wait? */
839         /* Sleep(100); */
840       };
841 #ifdef NEW_PACKET_LIST
842       /* Don't freeze/thaw the list when doing live capture */
843       /*new_packet_list_thaw();*/
844 #else
845       packet_list_thaw();
846 #endif
847       return CF_READ_ABORTED;
848     }
849     ENDTRY;
850     to_read--;
851   }
852
853   /* Cleanup and release all dfilter resources */
854   if (dfcode != NULL){
855     dfilter_free(dfcode);
856   }
857
858   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
859     cf->count, cf->state, *err);*/
860
861 #ifdef NEW_PACKET_LIST
862   /* Don't freeze/thaw the list when doing live capture */
863   /*new_packet_list_thaw();*/
864   /* With the new packet list the first packet
865    * isn't automatically selected.
866    */
867   if(!cf->current_frame)
868     new_packet_list_select_first_row();
869 #else
870   /* XXX - this causes "flickering" of the list */
871   packet_list_thaw();
872 #endif
873
874   /* moving to the end of the packet list - if the user requested so and
875      we have some new packets. */
876   if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
877 #ifdef NEW_PACKET_LIST
878     if(visible)
879       new_packet_list_moveto_end();
880 #else
881     /* this doesn't seem to work well with a frozen GTK_Clist, so do this after
882        packet_list_thaw() is done, see bugzilla 1188 */
883     /* XXX - this cheats and looks inside the packet list to find the final
884        row number. */
885     packet_list_moveto_end();
886 #endif /* NEW_PACKET_LIST */
887
888   if (cf->state == FILE_READ_ABORTED) {
889     /* Well, the user decided to exit Wireshark.  Return CF_READ_ABORTED
890        so that our caller can kill off the capture child process;
891        this will cause an EOF on the pipe from the child, so
892        "cf_finish_tail()" will be called, and it will clean up
893        and exit. */
894     return CF_READ_ABORTED;
895   } else if (*err != 0) {
896     /* We got an error reading the capture file.
897        XXX - pop up a dialog box instead? */
898     g_warning("Error \"%s\" while reading: \"%s\"\n",
899         wtap_strerror(*err), cf->filename);
900
901     return CF_READ_ERROR;
902   } else
903     return CF_READ_OK;
904 }
905
906 cf_read_status_t
907 cf_finish_tail(capture_file *cf, int *err)
908 {
909   gchar *err_info;
910   gint64 data_offset;
911   dfilter_t   *dfcode;
912   gboolean filtering_tap_listeners;
913   guint tap_flags;
914   gboolean compiled;
915
916   /* Compile the current display filter.
917    * We assume this will not fail since cf->dfilter is only set in
918    * cf_filter IFF the filter was valid.
919    */
920   compiled = dfilter_compile(cf->dfilter, &dfcode);
921   g_assert(!cf->dfilter || (compiled && dfcode));
922
923   /* Do we have any tap listeners with filters? */
924   filtering_tap_listeners = have_filtering_tap_listeners();
925
926   /* Get the union of the flags for all tap listeners. */
927   tap_flags = union_of_tap_listener_flags();
928
929   if(cf->wth == NULL) {
930     cf_close(cf);
931     return CF_READ_ERROR;
932   }
933
934 #ifdef NEW_PACKET_LIST
935   new_packet_list_check_end();
936   /* Don't freeze/thaw the list when doing live capture */
937   /*new_packet_list_freeze();*/
938 #else
939   packet_list_check_end();
940   packet_list_freeze();
941 #endif
942
943   while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
944     if (cf->state == FILE_READ_ABORTED) {
945       /* Well, the user decided to abort the read.  Break out of the
946          loop, and let the code below (which is called even if there
947      aren't any packets left to read) exit. */
948       break;
949     }
950     read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
951   }
952
953   /* Cleanup and release all dfilter resources */
954   if (dfcode != NULL){
955     dfilter_free(dfcode);
956   }
957
958 #ifdef NEW_PACKET_LIST
959   /* Don't freeze/thaw the list when doing live capture */
960   /*new_packet_list_thaw();*/
961 #else
962   packet_list_thaw();
963 #endif
964
965   if (cf->state == FILE_READ_ABORTED) {
966     /* Well, the user decided to abort the read.  We're only called
967        when the child capture process closes the pipe to us (meaning
968        it's probably exited), so we can just close the capture
969        file; we return CF_READ_ABORTED so our caller can do whatever
970        is appropriate when that happens. */
971     cf_close(cf);
972     return CF_READ_ABORTED;
973   }
974
975   if (auto_scroll_live && cf->plist_end != NULL)
976 #ifdef NEW_PACKET_LIST
977     new_packet_list_moveto_end();
978 #else
979     /* XXX - this cheats and looks inside the packet list to find the final
980        row number. */
981     packet_list_moveto_end();
982 #endif
983
984   /* We're done reading sequentially through the file. */
985   cf->state = FILE_READ_DONE;
986
987   /* We're done reading sequentially through the file; close the
988      sequential I/O side, to free up memory it requires. */
989   wtap_sequential_close(cf->wth);
990
991   /* Allow the protocol dissectors to free up memory that they
992    * don't need after the sequential run-through of the packets. */
993   postseq_cleanup_all_protocols();
994
995   /* Set the file encapsulation type now; we don't know what it is until
996      we've looked at all the packets, as we don't know until then whether
997      there's more than one type (and thus whether it's
998      WTAP_ENCAP_PER_PACKET). */
999   cf->lnk_t = wtap_file_encap(cf->wth);
1000
1001   if (*err != 0) {
1002     /* We got an error reading the capture file.
1003        XXX - pop up a dialog box? */
1004     return CF_READ_ERROR;
1005   } else {
1006     return CF_READ_OK;
1007   }
1008 }
1009 #endif /* HAVE_LIBPCAP */
1010
1011 const gchar *
1012 cf_get_display_name(capture_file *cf)
1013 {
1014   const gchar *displayname;
1015
1016   /* Return a name to use in displays */
1017   if (!cf->is_tempfile) {
1018     /* Get the last component of the file name, and use that. */
1019     if (cf->filename){
1020       displayname = get_basename(cf->filename);
1021     } else {
1022       displayname="(No file)";
1023     }
1024   } else {
1025     /* The file we read is a temporary file from a live capture;
1026        we don't mention its name. */
1027     if (cf->source) {
1028       displayname = cf->source;
1029     } else {
1030       displayname = "(Untitled)";
1031     }
1032   }
1033   return displayname;
1034 }
1035
1036 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1037   if (cf->source) {
1038     g_free(cf->source);
1039   }
1040
1041   if (source) {
1042     cf->source = g_strdup(source);
1043   } else {
1044     cf->source = g_strdup("");
1045   }
1046 }
1047
1048 const gchar *cf_get_tempfile_source(capture_file *cf) {
1049   if (!cf->source) {
1050     return "";
1051   }
1052
1053   return cf->source;
1054 }
1055
1056 /* XXX - use a macro instead? */
1057 int
1058 cf_get_packet_count(capture_file *cf)
1059 {
1060   return cf->count;
1061 }
1062
1063 /* XXX - use a macro instead? */
1064 void
1065 cf_set_packet_count(capture_file *cf, int packet_count)
1066 {
1067   cf->count = packet_count;
1068 }
1069
1070 /* XXX - use a macro instead? */
1071 gboolean
1072 cf_is_tempfile(capture_file *cf)
1073 {
1074   return cf->is_tempfile;
1075 }
1076
1077 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1078 {
1079   cf->is_tempfile = is_tempfile;
1080 }
1081
1082
1083 /* XXX - use a macro instead? */
1084 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1085 {
1086   cf->drops_known = drops_known;
1087 }
1088
1089 /* XXX - use a macro instead? */
1090 void cf_set_drops(capture_file *cf, guint32 drops)
1091 {
1092   cf->drops = drops;
1093 }
1094
1095 /* XXX - use a macro instead? */
1096 gboolean cf_get_drops_known(capture_file *cf)
1097 {
1098   return cf->drops_known;
1099 }
1100
1101 /* XXX - use a macro instead? */
1102 guint32 cf_get_drops(capture_file *cf)
1103 {
1104   return cf->drops;
1105 }
1106
1107 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1108 {
1109   cf->rfcode = rfcode;
1110 }
1111
1112 #ifdef NEW_PACKET_LIST
1113 static int
1114 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1115     dfilter_t *dfcode, gboolean filtering_tap_listeners,
1116     guint tap_flags,
1117     union wtap_pseudo_header *pseudo_header, const guchar *buf,
1118     gboolean refilter,
1119     gboolean add_to_packet_list)
1120 {
1121   gboolean  create_proto_tree = FALSE;
1122   epan_dissect_t edt;
1123   column_info *cinfo;
1124   gint row = -1;
1125
1126   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1127
1128   frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1129                                 &first_ts, &prev_dis_ts, &prev_cap_ts);
1130
1131   /* If either
1132     + we have a display filter and are re-applying it;
1133     + we have tap listeners with filters;
1134     + we have tap listeners that require a protocol tree;
1135
1136      allocate a protocol tree root node, so that we'll construct
1137      a protocol tree against which a filter expression can be
1138      evaluated. */
1139   if ((dfcode != NULL && refilter) ||
1140       filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1141       create_proto_tree = TRUE;
1142
1143   /* Dissect the frame. */
1144   epan_dissect_init(&edt, create_proto_tree, FALSE);
1145
1146   if (dfcode != NULL && refilter) {
1147       epan_dissect_prime_dfilter(&edt, dfcode);
1148   }
1149
1150   tap_queue_init(&edt);
1151   epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1152   tap_push_tapped_queue(&edt);
1153
1154   /* If we have a display filter, apply it if we're refiltering, otherwise
1155      leave the "passed_dfilter" flag alone.
1156
1157      If we don't have a display filter, set "passed_dfilter" to 1. */
1158   if (dfcode != NULL) {
1159     if (refilter) {
1160       fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1161     }
1162   } else
1163     fdata->flags.passed_dfilter = 1;
1164
1165   if (add_to_packet_list) {
1166     /* We fill the needed columns from new_packet_list */
1167       row = new_packet_list_append(cinfo, fdata, &edt.pi);
1168   }
1169
1170   if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
1171   {
1172     frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1173
1174     /* If we haven't yet seen the first frame, this is it.
1175
1176        XXX - we must do this before we add the row to the display,
1177        as, if the display's GtkCList's selection mode is
1178        GTK_SELECTION_BROWSE, when the first entry is added to it,
1179        "cf_select_packet()" will be called, and it will fetch the row
1180        data for the 0th row, and will get a null pointer rather than
1181        "fdata", as "gtk_clist_append()" won't yet have returned and
1182        thus "gtk_clist_set_row_data()" won't yet have been called.
1183
1184        We thus need to leave behind bread crumbs so that
1185        "cf_select_packet()" can find this frame.  See the comment
1186        in "cf_select_packet()". */
1187     if (cf->first_displayed == NULL)
1188       cf->first_displayed = fdata;
1189
1190     /* This is the last frame we've seen so far. */
1191     cf->last_displayed = fdata;
1192
1193     cf->displayed_count++;
1194   }
1195
1196   epan_dissect_cleanup(&edt);
1197   return row;
1198 }
1199
1200 #else
1201
1202 static int
1203 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1204     dfilter_t *dfcode, gboolean filtering_tap_listeners,
1205     guint tap_flags,
1206     union wtap_pseudo_header *pseudo_header, const guchar *buf,
1207     gboolean refilter,
1208     gboolean add_to_packet_list _U_)
1209 {
1210   gboolean  create_proto_tree = FALSE;
1211   epan_dissect_t edt;
1212   column_info *cinfo;
1213   gint row = -1;
1214
1215   cinfo = &cf->cinfo;
1216
1217   /* just add some value here until we know if it is being displayed or not */
1218   fdata->cum_bytes  = cum_bytes + fdata->pkt_len;
1219
1220   frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1221                                 &first_ts, &prev_dis_ts, &prev_cap_ts);
1222
1223   /* If either
1224
1225     we have a display filter and are re-applying it;
1226
1227     we have a list of color filters;
1228
1229     we have tap listeners with filters;
1230
1231     we have tap listeners that require a protocol tree;
1232
1233     we have custom columns;
1234
1235      allocate a protocol tree root node, so that we'll construct
1236      a protocol tree against which a filter expression can be
1237      evaluated. */
1238   if ((dfcode != NULL && refilter) ||
1239       color_filters_used() ||
1240       have_custom_cols(cinfo) ||
1241       filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
1242       create_proto_tree = TRUE;
1243
1244   /* Dissect the frame. */
1245   epan_dissect_init(&edt, create_proto_tree, FALSE);
1246
1247   if (dfcode != NULL && refilter) {
1248       epan_dissect_prime_dfilter(&edt, dfcode);
1249   }
1250
1251   /* prepare color filters */
1252   color_filters_prime_edt(&edt);
1253   col_custom_prime_edt(&edt, cinfo);
1254
1255   tap_queue_init(&edt);
1256   epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
1257   tap_push_tapped_queue(&edt);
1258
1259   /* If we have a display filter, apply it if we're refiltering, otherwise
1260      leave the "passed_dfilter" flag alone.
1261
1262      If we don't have a display filter, set "passed_dfilter" to 1. */
1263   if (dfcode != NULL) {
1264     if (refilter) {
1265       fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
1266     }
1267   } else
1268     fdata->flags.passed_dfilter = 1;
1269
1270   if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) )
1271   {
1272     frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
1273
1274     epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
1275
1276     /* If we haven't yet seen the first frame, this is it.
1277
1278        XXX - we must do this before we add the row to the display,
1279        as, if the display's GtkCList's selection mode is
1280        GTK_SELECTION_BROWSE, when the first entry is added to it,
1281        "cf_select_packet()" will be called, and it will fetch the row
1282        data for the 0th row, and will get a null pointer rather than
1283        "fdata", as "gtk_clist_append()" won't yet have returned and
1284        thus "gtk_clist_set_row_data()" won't yet have been called.
1285
1286        We thus need to leave behind bread crumbs so that
1287        "cf_select_packet()" can find this frame.  See the comment
1288        in "cf_select_packet()". */
1289     if (cf->first_displayed == NULL)
1290       cf->first_displayed = fdata;
1291
1292     /* This is the last frame we've seen so far. */
1293     cf->last_displayed = fdata;
1294
1295     row = packet_list_append(cinfo->col_data, fdata);
1296
1297     /* colorize packet: first apply color filters
1298      * then if packet is marked, use preferences to overwrite color
1299      * we do both to make sure that when a packet gets un-marked, the
1300      * color will be correctly set (fixes bug 2038)
1301      */
1302      fdata->color_filter = color_filters_colorize_packet(row, &edt);
1303      if (fdata->flags.marked) {
1304        packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
1305      }
1306      if (fdata->flags.ignored) {
1307        packet_list_set_colors(row, &prefs.gui_ignored_fg, &prefs.gui_ignored_bg);
1308      }
1309
1310     cf->displayed_count++;
1311   }
1312
1313   epan_dissect_cleanup(&edt);
1314   return row;
1315 }
1316 #endif
1317
1318 /* read in a new packet */
1319 /* returns the row of the new packet in the packet list or -1 if not displayed */
1320 static int
1321 read_packet(capture_file *cf, dfilter_t *dfcode,
1322             gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
1323 {
1324   const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1325   union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1326   const guchar *buf = wtap_buf_ptr(cf->wth);
1327   frame_data   *fdata;
1328   int           passed;
1329   int           row = -1;
1330
1331   cf->count++;
1332
1333   /* Allocate the next list entry, and add it to the list.
1334    * memory chunks have been deprecated in favor of the slice allocator,
1335    * which has been added in 2.10
1336    */
1337 #if GLIB_CHECK_VERSION(2,10,0)
1338   fdata = g_slice_new(frame_data);
1339 #else
1340   fdata = g_mem_chunk_alloc(cf->plist_chunk);
1341 #endif
1342
1343   frame_data_init(fdata, cf->count, phdr, offset, cum_bytes);
1344
1345 #ifdef NEW_PACKET_LIST
1346   fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
1347   fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
1348 #endif
1349
1350   passed = TRUE;
1351   if (cf->rfcode) {
1352     epan_dissect_t edt;
1353     epan_dissect_init(&edt, TRUE, FALSE);
1354     epan_dissect_prime_dfilter(&edt, cf->rfcode);
1355     epan_dissect_run(&edt, pseudo_header, buf, fdata, NULL);
1356     passed = dfilter_apply_edt(cf->rfcode, &edt);
1357     epan_dissect_cleanup(&edt);
1358   }
1359
1360   if (passed) {
1361     cap_file_add_fdata(cf, fdata);
1362
1363     cf->f_datalen = offset + fdata->cap_len;
1364
1365     if (!cf->redissecting) {
1366       row = add_packet_to_packet_list(fdata, cf, dfcode,
1367                                       filtering_tap_listeners, tap_flags,
1368                                       pseudo_header, buf, TRUE, TRUE);
1369     }
1370   } else {
1371     /* We didn't pass read filter so roll back count */
1372     cf->count--;
1373
1374     /* XXX - if we didn't have read filters, or if we could avoid
1375        allocating the "frame_data" structure until we knew whether
1376        the frame passed the read filter, we could use a G_ALLOC_ONLY
1377        memory chunk...
1378
1379        ...but, at least in one test I did, where I just made the chunk
1380        a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
1381        seem to save a noticeable amount of time or space. */
1382 #if GLIB_CHECK_VERSION(2,10,0)
1383   /* memory chunks have been deprecated in favor of the slice allocator,
1384    * which has been added in 2.10
1385    */
1386     g_slice_free(frame_data,fdata);
1387 #else
1388     g_mem_chunk_free(cf->plist_chunk, fdata);
1389 #endif
1390   }
1391
1392   return row;
1393 }
1394
1395 cf_status_t
1396 cf_merge_files(char **out_filenamep, int in_file_count,
1397                char *const *in_filenames, int file_type, gboolean do_append)
1398 {
1399   merge_in_file_t  *in_files;
1400   wtap             *wth;
1401   char             *out_filename;
1402   char             *tmpname;
1403   int               out_fd;
1404   wtap_dumper      *pdh;
1405   int               open_err, read_err, write_err, close_err;
1406   gchar            *err_info;
1407   int               err_fileno;
1408   int               i;
1409   char              errmsg_errno[1024+1];
1410   const char       *errmsg;
1411   gboolean          got_read_error = FALSE, got_write_error = FALSE;
1412   gint64            data_offset;
1413   progdlg_t        *progbar = NULL;
1414   gboolean          stop_flag;
1415   gint64            f_len, file_pos;
1416   float             progbar_val;
1417   GTimeVal          start_time;
1418   gchar             status_str[100];
1419   gint64            progbar_nextstep;
1420   gint64            progbar_quantum;
1421
1422   /* open the input files */
1423   if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1424                            &open_err, &err_info, &err_fileno)) {
1425     g_free(in_files);
1426     cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1427                               FALSE, 0);
1428     return CF_ERROR;
1429   }
1430
1431   if (*out_filenamep != NULL) {
1432     out_filename = *out_filenamep;
1433     out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1434     if (out_fd == -1)
1435       open_err = errno;
1436   } else {
1437     out_fd = create_tempfile(&tmpname, "wireshark");
1438     if (out_fd == -1)
1439       open_err = errno;
1440     out_filename = g_strdup(tmpname);
1441     *out_filenamep = out_filename;
1442   }
1443   if (out_fd == -1) {
1444     err_info = NULL;
1445     merge_close_in_files(in_file_count, in_files);
1446     g_free(in_files);
1447     cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1448     return CF_ERROR;
1449   }
1450
1451   pdh = wtap_dump_fdopen(out_fd, file_type,
1452       merge_select_frame_type(in_file_count, in_files),
1453       merge_max_snapshot_length(in_file_count, in_files),
1454       FALSE /* compressed */, &open_err);
1455   if (pdh == NULL) {
1456     ws_close(out_fd);
1457     merge_close_in_files(in_file_count, in_files);
1458     g_free(in_files);
1459     cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1460                               file_type);
1461     return CF_ERROR;
1462   }
1463
1464   /* Get the sum of the sizes of all the files. */
1465   f_len = 0;
1466   for (i = 0; i < in_file_count; i++)
1467     f_len += in_files[i].size;
1468
1469   /* Update the progress bar when it gets to this value. */
1470   progbar_nextstep = 0;
1471   /* When we reach the value that triggers a progress bar update,
1472      bump that value by this amount. */
1473   progbar_quantum = f_len/N_PROGBAR_UPDATES;
1474   /* Progress so far. */
1475   progbar_val = 0.0f;
1476
1477   stop_flag = FALSE;
1478   g_get_current_time(&start_time);
1479
1480   /* do the merge (or append) */
1481   for (;;) {
1482     if (do_append)
1483       wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1484                                      &err_info);
1485     else
1486       wth = merge_read_packet(in_file_count, in_files, &read_err,
1487                               &err_info);
1488     if (wth == NULL) {
1489       if (read_err != 0)
1490         got_read_error = TRUE;
1491       break;
1492     }
1493
1494     /* Get the sum of the data offsets in all of the files. */
1495     data_offset = 0;
1496     for (i = 0; i < in_file_count; i++)
1497       data_offset += in_files[i].data_offset;
1498
1499     /* Create the progress bar if necessary.
1500        We check on every iteration of the loop, so that it takes no
1501        longer than the standard time to create it (otherwise, for a
1502        large file, we might take considerably longer than that standard
1503        time in order to get to the next progress bar step). */
1504     if (progbar == NULL) {
1505       progbar = delayed_create_progress_dlg("Merging", "files",
1506         FALSE, &stop_flag, &start_time, progbar_val);
1507     }
1508
1509     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1510        when we update it, we have to run the GTK+ main loop to get it
1511        to repaint what's pending, and doing so may involve an "ioctl()"
1512        to see if there's any pending input from an X server, and doing
1513        that for every packet can be costly, especially on a big file. */
1514     if (data_offset >= progbar_nextstep) {
1515         /* Get the sum of the seek positions in all of the files. */
1516         file_pos = 0;
1517         for (i = 0; i < in_file_count; i++)
1518           file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1519         progbar_val = (gfloat) file_pos / (gfloat) f_len;
1520         if (progbar_val > 1.0f) {
1521           /* Some file probably grew while we were reading it.
1522              That "shouldn't happen", so we'll just clip the progress
1523              value at 1.0. */
1524           progbar_val = 1.0f;
1525         }
1526         if (progbar != NULL) {
1527           g_snprintf(status_str, sizeof(status_str),
1528                      "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1529                      file_pos / 1024, f_len / 1024);
1530           update_progress_dlg(progbar, progbar_val, status_str);
1531         }
1532         progbar_nextstep += progbar_quantum;
1533     }
1534
1535     if (stop_flag) {
1536       /* Well, the user decided to abort the merge. */
1537       break;
1538     }
1539
1540     if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1541          wtap_buf_ptr(wth), &write_err)) {
1542       got_write_error = TRUE;
1543       break;
1544     }
1545   }
1546
1547   /* We're done merging the files; destroy the progress bar if it was created. */
1548   if (progbar != NULL)
1549     destroy_progress_dlg(progbar);
1550
1551   merge_close_in_files(in_file_count, in_files);
1552   if (!got_read_error && !got_write_error) {
1553     if (!wtap_dump_close(pdh, &write_err))
1554       got_write_error = TRUE;
1555   } else
1556     wtap_dump_close(pdh, &close_err);
1557
1558   if (got_read_error) {
1559     /*
1560      * Find the file on which we got the error, and report the error.
1561      */
1562     for (i = 0; i < in_file_count; i++) {
1563       if (in_files[i].state == GOT_ERROR) {
1564     /* Put up a message box noting that a read failed somewhere along
1565        the line. */
1566     switch (read_err) {
1567
1568     case WTAP_ERR_UNSUPPORTED_ENCAP:
1569       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1570            "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1571            err_info);
1572       g_free(err_info);
1573       errmsg = errmsg_errno;
1574       break;
1575
1576     case WTAP_ERR_CANT_READ:
1577       errmsg = "An attempt to read from the capture file %s failed for"
1578            " some unknown reason.";
1579       break;
1580
1581     case WTAP_ERR_SHORT_READ:
1582       errmsg = "The capture file %s appears to have been cut short"
1583            " in the middle of a packet.";
1584       break;
1585
1586     case WTAP_ERR_BAD_RECORD:
1587       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1588            "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1589            err_info);
1590       g_free(err_info);
1591       errmsg = errmsg_errno;
1592       break;
1593
1594     default:
1595       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1596            "An error occurred while reading the"
1597            " capture file %%s: %s.", wtap_strerror(read_err));
1598       errmsg = errmsg_errno;
1599       break;
1600     }
1601         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
1602       }
1603     }
1604   }
1605
1606   if (got_write_error) {
1607     /* Put up an alert box for the write error. */
1608     cf_write_failure_alert_box(out_filename, write_err);
1609   }
1610
1611   if (got_read_error || got_write_error || stop_flag) {
1612     /* Callers aren't expected to treat an error or an explicit abort
1613        differently - we put up error dialogs ourselves, so they don't
1614        have to. */
1615     return CF_ERROR;
1616   } else
1617     return CF_OK;
1618 }
1619
1620 cf_status_t
1621 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1622 {
1623   const char *filter_new = dftext ? dftext : "";
1624   const char *filter_old = cf->dfilter ? cf->dfilter : "";
1625   dfilter_t   *dfcode;
1626   GTimeVal     start_time;
1627
1628   /* if new filter equals old one, do nothing unless told to do so */
1629   if (!force && strcmp(filter_new, filter_old) == 0) {
1630     return CF_OK;
1631   }
1632
1633   dfcode=NULL;
1634
1635   if (dftext == NULL) {
1636     /* The new filter is an empty filter (i.e., display all packets).
1637      * so leave dfcode==NULL
1638      */
1639   } else {
1640     /*
1641      * We have a filter; make a copy of it (as we'll be saving it),
1642      * and try to compile it.
1643      */
1644     dftext = g_strdup(dftext);
1645     if (!dfilter_compile(dftext, &dfcode)) {
1646       /* The attempt failed; report an error. */
1647       gchar *safe_dftext = simple_dialog_format_message(dftext);
1648       gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1649       dfilter_error_msg);
1650       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1651           "%s%s%s\n"
1652           "\n"
1653           "The following display filter isn't a valid display filter:\n%s\n"
1654           "See the help for a description of the display filter syntax.",
1655           simple_dialog_primary_start(), safe_dfilter_error_msg,
1656           simple_dialog_primary_end(), safe_dftext);
1657       g_free(safe_dfilter_error_msg);
1658       g_free(safe_dftext);
1659       g_free(dftext);
1660       return CF_ERROR;
1661     }
1662
1663     /* Was it empty? */
1664     if (dfcode == NULL) {
1665       /* Yes - free the filter text, and set it to null. */
1666       g_free(dftext);
1667       dftext = NULL;
1668     }
1669   }
1670
1671   /* We have a valid filter.  Replace the current filter. */
1672   g_free(cf->dfilter);
1673   cf->dfilter = dftext;
1674   g_get_current_time(&start_time);
1675
1676
1677   /* Now rescan the packet list, applying the new filter, but not
1678      throwing away information constructed on a previous pass. */
1679   if (dftext == NULL) {
1680     rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1681   } else {
1682     rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1683   }
1684
1685   /* Cleanup and release all dfilter resources */
1686   dfilter_free(dfcode);
1687
1688   return CF_OK;
1689 }
1690
1691 void
1692 cf_colorize_packets(capture_file *cf)
1693 {
1694   rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1695 }
1696
1697 void
1698 cf_reftime_packets(capture_file *cf)
1699 {
1700
1701 #ifdef NEW_PACKET_LIST
1702   ref_time_packets(cf);
1703 #else
1704   rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1705 #endif
1706 }
1707
1708 void
1709 cf_redissect_packets(capture_file *cf)
1710 {
1711   rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1712 }
1713
1714 /* Rescan the list of packets, reconstructing the CList.
1715
1716    "action" describes why we're doing this; it's used in the progress
1717    dialog box.
1718
1719    "action_item" describes what we're doing; it's used in the progress
1720    dialog box.
1721
1722    "refilter" is TRUE if we need to re-evaluate the filter expression.
1723
1724    "redissect" is TRUE if we need to make the dissectors reconstruct
1725    any state information they have (because a preference that affects
1726    some dissector has changed, meaning some dissector might construct
1727    its state differently from the way it was constructed the last time). */
1728 #ifdef NEW_PACKET_LIST
1729 static void
1730 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1731         gboolean refilter, gboolean redissect)
1732 {
1733     /* Rescan packets new packet list */
1734   frame_data *fdata;
1735   progdlg_t  *progbar = NULL;
1736   gboolean    stop_flag;
1737   int         count;
1738   int         err;
1739   gchar      *err_info;
1740   frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1741   int         selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1742   gboolean    selected_frame_seen;
1743   int         frame_num;
1744   float       progbar_val;
1745   GTimeVal    start_time;
1746   gchar       status_str[100];
1747   int         progbar_nextstep;
1748   int         progbar_quantum;
1749   dfilter_t   *dfcode;
1750   gboolean    filtering_tap_listeners;
1751   guint       tap_flags;
1752   gboolean    add_to_packet_list = FALSE;
1753   gboolean compiled;
1754
1755   /* Compile the current display filter.
1756    * We assume this will not fail since cf->dfilter is only set in
1757    * cf_filter IFF the filter was valid.
1758    */
1759   compiled = dfilter_compile(cf->dfilter, &dfcode);
1760   g_assert(!cf->dfilter || (compiled && dfcode));
1761
1762   /* Do we have any tap listeners with filters? */
1763   filtering_tap_listeners = have_filtering_tap_listeners();
1764
1765   /* Get the union of the flags for all tap listeners. */
1766   tap_flags = union_of_tap_listener_flags();
1767
1768   reset_tap_listeners();
1769   /* Which frame, if any, is the currently selected frame?
1770      XXX - should the selected frame or the focus frame be the "current"
1771      frame, that frame being the one from which "Find Frame" searches
1772      start? */
1773   selected_frame = cf->current_frame;
1774
1775   /* Mark frane num as not found */
1776   selected_frame_num = -1;
1777
1778   /* Freeze the packet list while we redo it, so we don't get any
1779      screen updates while it happens. */
1780   new_packet_list_freeze();
1781
1782   if (redissect) {
1783     /* We need to re-initialize all the state information that protocols
1784        keep, because some preference that controls a dissector has changed,
1785        which might cause the state information to be constructed differently
1786        by that dissector. */
1787
1788     /* We might receive new packets while redissecting, and we don't
1789        want to dissect those before their time. */
1790     cf->redissecting = TRUE;
1791
1792     /* Cleanup all data structures used for dissection. */
1793     cleanup_dissection();
1794     /* Initialize all data structures used for dissection. */
1795     init_dissection();
1796
1797     /* We need to redissect the packets so we have to discard our old
1798      * packet list store. */
1799     new_packet_list_clear();
1800     add_to_packet_list = TRUE;
1801   }
1802
1803   /* We don't yet know which will be the first and last frames displayed. */
1804   cf->first_displayed = NULL;
1805   cf->last_displayed = NULL;
1806
1807   /* We currently don't display any packets */
1808   cf->displayed_count = 0;
1809
1810   /* Iterate through the list of frames.  Call a routine for each frame
1811      to check whether it should be displayed and, if so, add it to
1812      the display list. */
1813   nstime_set_unset(&first_ts);
1814   nstime_set_unset(&prev_dis_ts);
1815   nstime_set_unset(&prev_cap_ts);
1816   cum_bytes = 0;
1817
1818   /* Update the progress bar when it gets to this value. */
1819   progbar_nextstep = 0;
1820   /* When we reach the value that triggers a progress bar update,
1821      bump that value by this amount. */
1822   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1823   /* Count of packets at which we've looked. */
1824   count = 0;
1825   /* Progress so far. */
1826   progbar_val = 0.0f;
1827
1828   stop_flag = FALSE;
1829   g_get_current_time(&start_time);
1830
1831   /* no previous row yet */
1832   frame_num = -1;
1833   prev_frame_num = -1;
1834   prev_frame = NULL;
1835
1836   preceding_frame_num = -1;
1837   preceding_frame = NULL;
1838   following_frame_num = -1;
1839   following_frame = NULL;
1840
1841   selected_frame_seen = FALSE;
1842
1843   for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
1844     /* Create the progress bar if necessary.
1845        We check on every iteration of the loop, so that it takes no
1846        longer than the standard time to create it (otherwise, for a
1847        large file, we might take considerably longer than that standard
1848        time in order to get to the next progress bar step). */
1849     if (progbar == NULL)
1850       progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1851                                             &stop_flag, &start_time,
1852                                             progbar_val);
1853
1854     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1855        when we update it, we have to run the GTK+ main loop to get it
1856        to repaint what's pending, and doing so may involve an "ioctl()"
1857        to see if there's any pending input from an X server, and doing
1858        that for every packet can be costly, especially on a big file. */
1859     if (count >= progbar_nextstep) {
1860       /* let's not divide by zero. I should never be started
1861        * with count == 0, so let's assert that
1862        */
1863       g_assert(cf->count > 0);
1864       progbar_val = (gfloat) count / cf->count;
1865
1866       if (progbar != NULL) {
1867         g_snprintf(status_str, sizeof(status_str),
1868                   "%4u of %u frames", count, cf->count);
1869         update_progress_dlg(progbar, progbar_val, status_str);
1870       }
1871
1872       progbar_nextstep += progbar_quantum;
1873     }
1874
1875     if (stop_flag) {
1876       /* Well, the user decided to abort the filtering.  Just stop.
1877
1878          XXX - go back to the previous filter?  Users probably just
1879      want not to wait for a filtering operation to finish;
1880      unless we cancel by having no filter, reverting to the
1881      previous filter will probably be even more expensive than
1882      continuing the filtering, as it involves going back to the
1883      beginning and filtering, and even with no filter we currently
1884      have to re-generate the entire clist, which is also expensive.
1885
1886      I'm not sure what Network Monitor does, but it doesn't appear
1887      to give you an unfiltered display if you cancel. */
1888       break;
1889     }
1890
1891     count++;
1892
1893     if (redissect) {
1894       /* Since all state for the frame was destroyed, mark the frame
1895        * as not visited, free the GSList referring to the state
1896        * data (the per-frame data itself was freed by
1897        * "init_dissection()"), and null out the GSList pointer. */
1898       fdata->flags.visited = 0;
1899       frame_data_cleanup(fdata);
1900
1901       /* cleanup_dissection() calls se_free_all();
1902        * And after that fdata->col_text (which is allocated using se_alloc0())
1903        * no longer points to valid memory.
1904        */
1905         fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
1906         fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
1907     }
1908
1909     if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1910         cf->pd, fdata->cap_len, &err, &err_info)) {
1911             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1912             cf_read_error_message(err, err_info), cf->filename);
1913             break;
1914     }
1915
1916     /* If the previous frame is displayed, and we haven't yet seen the
1917        selected frame, remember that frame - it's the closest one we've
1918        yet seen before the selected frame. */
1919     if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1920       preceding_frame_num = prev_frame_num;
1921       preceding_frame = prev_frame;
1922     }
1923     add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
1924                                     tap_flags, &cf->pseudo_header, cf->pd,
1925                                     refilter,
1926                                     add_to_packet_list);
1927
1928     /* If this frame is displayed, and this is the first frame we've
1929        seen displayed after the selected frame, remember this frame -
1930        it's the closest one we've yet seen at or after the selected
1931        frame. */
1932     if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1933       following_frame_num = fdata->num;
1934       following_frame = fdata;
1935     }
1936     if (fdata == selected_frame) {
1937       selected_frame_seen = TRUE;
1938       if (fdata->flags.passed_dfilter)
1939           selected_frame_num = fdata->num;
1940     }
1941
1942     /* Remember this frame - it'll be the previous frame
1943        on the next pass through the loop. */
1944     prev_frame_num = fdata->num;
1945     prev_frame = fdata;
1946   }
1947
1948   /* We are done redissecting the packet list. */
1949   cf->redissecting = FALSE;
1950
1951   if (redissect) {
1952     /* Clear out what remains of the visited flags and per-frame data
1953        pointers.
1954
1955        XXX - that may cause various forms of bogosity when dissecting
1956        these frames, as they won't have been seen by this sequential
1957        pass, but the only alternative I see is to keep scanning them
1958        even though the user requested that the scan stop, and that
1959        would leave the user stuck with an Wireshark grinding on
1960        until it finishes.  Should we just stick them with that? */
1961     for (; fdata != NULL; fdata = fdata->next) {
1962       fdata->flags.visited = 0;
1963       frame_data_cleanup(fdata);
1964     }
1965   }
1966
1967   /* We're done filtering the packets; destroy the progress bar if it
1968      was created. */
1969   if (progbar != NULL)
1970     destroy_progress_dlg(progbar);
1971
1972   /* Unfreeze the packet list. */
1973   if (!add_to_packet_list)
1974     new_packet_list_recreate_visible_rows();
1975
1976   /* Compute the time it took to filter the file */
1977   compute_elapsed(&start_time);
1978
1979   new_packet_list_thaw();
1980
1981   if (selected_frame_num == -1) {
1982     /* The selected frame didn't pass the filter. */
1983     if (selected_frame == NULL) {
1984       /* That's because there *was* no selected frame.  Make the first
1985          displayed frame the current frame. */
1986       selected_frame_num = 0;
1987     } else {
1988       /* Find the nearest displayed frame to the selected frame (whether
1989          it's before or after that frame) and make that the current frame.
1990          If the next and previous displayed frames are equidistant from the
1991          selected frame, choose the next one. */
1992       g_assert(following_frame == NULL ||
1993                following_frame->num >= selected_frame->num);
1994       g_assert(preceding_frame == NULL ||
1995                preceding_frame->num <= selected_frame->num);
1996       if (following_frame == NULL) {
1997         /* No frame after the selected frame passed the filter, so we
1998            have to select the last displayed frame before the selected
1999            frame. */
2000         selected_frame_num = preceding_frame_num;
2001         selected_frame = preceding_frame;
2002       } else if (preceding_frame == NULL) {
2003         /* No frame before the selected frame passed the filter, so we
2004            have to select the first displayed frame after the selected
2005            frame. */
2006         selected_frame_num = following_frame_num;
2007         selected_frame = following_frame;
2008       } else {
2009         /* Frames before and after the selected frame passed the filter, so
2010            we'll select the previous frame */
2011         selected_frame_num = preceding_frame_num;
2012         selected_frame = preceding_frame;
2013       }
2014     }
2015   }
2016
2017   if (selected_frame_num == -1) {
2018     /* There are no frames displayed at all. */
2019     cf_unselect_packet(cf);
2020   } else {
2021     /* Either the frame that was selected passed the filter, or we've
2022        found the nearest displayed frame to that frame.  Select it, make
2023        it the focus row, and make it visible. */
2024     /* Set to invalid to force update of packet list and packet details */
2025     cf->current_row = -1;
2026     if (selected_frame_num == 0) {
2027       new_packet_list_select_first_row();
2028     }else{
2029       new_packet_list_find_row_from_data(selected_frame, TRUE);
2030     }
2031   }
2032
2033   /* Cleanup and release all dfilter resources */
2034   dfilter_free(dfcode);
2035 }
2036
2037 #else
2038
2039 static void
2040 rescan_packets(capture_file *cf, const char *action, const char *action_item,
2041         gboolean refilter, gboolean redissect)
2042 {
2043   frame_data *fdata;
2044   progdlg_t  *progbar = NULL;
2045   gboolean    stop_flag;
2046   int         count;
2047   int         err;
2048   gchar      *err_info;
2049   frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
2050   int         selected_row, prev_row, preceding_row, following_row;
2051   gboolean    selected_frame_seen;
2052   int         row;
2053   float       progbar_val;
2054   GTimeVal    start_time;
2055   gchar       status_str[100];
2056   int         progbar_nextstep;
2057   int         progbar_quantum;
2058   dfilter_t   *dfcode;
2059   gboolean    filtering_tap_listeners;
2060   guint       tap_flags;
2061   gboolean    add_to_packet_list = TRUE;
2062   gboolean compiled;
2063
2064   /* Compile the current display filter.
2065    * We assume this will not fail since cf->dfilter is only set in
2066    * cf_filter IFF the filter was valid.
2067    */
2068   compiled = dfilter_compile(cf->dfilter, &dfcode);
2069   g_assert(!cf->dfilter || (compiled && dfcode));
2070
2071   /* Do we have any tap listeners with filters? */
2072   filtering_tap_listeners = have_filtering_tap_listeners();
2073
2074   /* Get the union of the flags for all tap listeners. */
2075   tap_flags = union_of_tap_listener_flags();
2076
2077   reset_tap_listeners();
2078   /* Which frame, if any, is the currently selected frame?
2079      XXX - should the selected frame or the focus frame be the "current"
2080      frame, that frame being the one from which "Find Frame" searches
2081      start? */
2082   selected_frame = cf->current_frame;
2083
2084   /* We don't yet know what row that frame will be on, if any, after we
2085      rebuild the clist, however. */
2086   selected_row = -1;
2087
2088   /* Freeze the packet list while we redo it, so we don't get any
2089      screen updates while it happens. */
2090   packet_list_freeze();
2091
2092   /* Clear it out. */
2093   packet_list_clear();
2094
2095   if (redissect) {
2096     /* We need to re-initialize all the state information that protocols
2097        keep, because some preference that controls a dissector has changed,
2098        which might cause the state information to be constructed differently
2099        by that dissector. */
2100
2101     /* We might receive new packets while redissecting, and we don't
2102        want to dissect those before their time. */
2103     cf->redissecting = TRUE;
2104
2105     /* Cleanup all data structures used for dissection. */
2106     cleanup_dissection();
2107     /* Initialize all data structures used for dissection. */
2108     init_dissection();
2109
2110   }
2111
2112   /* We don't yet know which will be the first and last frames displayed. */
2113   cf->first_displayed = NULL;
2114   cf->last_displayed = NULL;
2115
2116   reset_elapsed();
2117
2118   /* We currently don't display any packets */
2119   cf->displayed_count = 0;
2120
2121   /* Iterate through the list of frames.  Call a routine for each frame
2122      to check whether it should be displayed and, if so, add it to
2123      the display list. */
2124   nstime_set_unset(&first_ts);
2125   nstime_set_unset(&prev_dis_ts);
2126   nstime_set_unset(&prev_cap_ts);
2127   cum_bytes = 0;
2128
2129   /* Update the progress bar when it gets to this value. */
2130   progbar_nextstep = 0;
2131   /* When we reach the value that triggers a progress bar update,
2132      bump that value by this amount. */
2133   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2134   /* Count of packets at which we've looked. */
2135   count = 0;
2136   /* Progress so far. */
2137   progbar_val = 0.0f;
2138
2139   stop_flag = FALSE;
2140   g_get_current_time(&start_time);
2141
2142   row = -1;     /* no previous row yet */
2143   prev_row = -1;
2144   prev_frame = NULL;
2145
2146   preceding_row = -1;
2147   preceding_frame = NULL;
2148   following_row = -1;
2149   following_frame = NULL;
2150
2151   selected_frame_seen = FALSE;
2152
2153   for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
2154     /* Create the progress bar if necessary.
2155        We check on every iteration of the loop, so that it takes no
2156        longer than the standard time to create it (otherwise, for a
2157        large file, we might take considerably longer than that standard
2158        time in order to get to the next progress bar step). */
2159     if (progbar == NULL)
2160       progbar = delayed_create_progress_dlg(action, action_item, TRUE,
2161                                             &stop_flag, &start_time,
2162                                             progbar_val);
2163
2164     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2165        when we update it, we have to run the GTK+ main loop to get it
2166        to repaint what's pending, and doing so may involve an "ioctl()"
2167        to see if there's any pending input from an X server, and doing
2168        that for every packet can be costly, especially on a big file. */
2169     if (count >= progbar_nextstep) {
2170       /* let's not divide by zero. I should never be started
2171        * with count == 0, so let's assert that
2172        */
2173       g_assert(cf->count > 0);
2174       progbar_val = (gfloat) count / cf->count;
2175
2176       if (progbar != NULL) {
2177         g_snprintf(status_str, sizeof(status_str),
2178                   "%4u of %u frames", count, cf->count);
2179         update_progress_dlg(progbar, progbar_val, status_str);
2180       }
2181
2182       progbar_nextstep += progbar_quantum;
2183     }
2184
2185     if (stop_flag) {
2186       /* Well, the user decided to abort the filtering.  Just stop.
2187
2188          XXX - go back to the previous filter?  Users probably just
2189      want not to wait for a filtering operation to finish;
2190      unless we cancel by having no filter, reverting to the
2191      previous filter will probably be even more expensive than
2192      continuing the filtering, as it involves going back to the
2193      beginning and filtering, and even with no filter we currently
2194      have to re-generate the entire clist, which is also expensive.
2195
2196      I'm not sure what Network Monitor does, but it doesn't appear
2197      to give you an unfiltered display if you cancel. */
2198       break;
2199     }
2200
2201     count++;
2202
2203     if (redissect) {
2204       /* Since all state for the frame was destroyed, mark the frame
2205        * as not visited, free the GSList referring to the state
2206        * data (the per-frame data itself was freed by
2207        * "init_dissection()"), and null out the GSList pointer.
2208        */
2209       fdata->flags.visited = 0;
2210       frame_data_cleanup(fdata);
2211     }
2212
2213     if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
2214         cf->pd, fdata->cap_len, &err, &err_info)) {
2215             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2216             cf_read_error_message(err, err_info), cf->filename);
2217             break;
2218     }
2219
2220     /* If the previous frame is displayed, and we haven't yet seen the
2221        selected frame, remember that frame - it's the closest one we've
2222        yet seen before the selected frame. */
2223     if (prev_row != -1 && !selected_frame_seen) {
2224       preceding_row = prev_row;
2225       preceding_frame = prev_frame;
2226     }
2227     row = add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
2228                                     tap_flags, &cf->pseudo_header, cf->pd,
2229                                     refilter,
2230                                     add_to_packet_list);
2231
2232     /* If this frame is displayed, and this is the first frame we've
2233        seen displayed after the selected frame, remember this frame -
2234        it's the closest one we've yet seen at or after the selected
2235        frame. */
2236     if (row != -1 && selected_frame_seen && following_row == -1) {
2237       following_row = row;
2238       following_frame = fdata;
2239     }
2240     if (fdata == selected_frame) {
2241       selected_row = row;
2242       selected_frame_seen = TRUE;
2243     }
2244
2245     /* Remember this row/frame - it'll be the previous row/frame
2246        on the next pass through the loop. */
2247     prev_row = row;
2248     prev_frame = fdata;
2249   }
2250
2251   /* We are done redissecting the packet list. */
2252   cf->redissecting = FALSE;
2253
2254   if (redissect) {
2255     /* Clear out what remains of the visited flags and per-frame data
2256        pointers.
2257
2258        XXX - that may cause various forms of bogosity when dissecting
2259        these frames, as they won't have been seen by this sequential
2260        pass, but the only alternative I see is to keep scanning them
2261        even though the user requested that the scan stop, and that
2262        would leave the user stuck with an Wireshark grinding on
2263        until it finishes.  Should we just stick them with that? */
2264     for (; fdata != NULL; fdata = fdata->next) {
2265       fdata->flags.visited = 0;
2266       frame_data_cleanup(fdata);
2267     }
2268   }
2269
2270   /* We're done filtering the packets; destroy the progress bar if it
2271      was created. */
2272   if (progbar != NULL)
2273     destroy_progress_dlg(progbar);
2274
2275   /* Unfreeze the packet list. */
2276   packet_list_thaw();
2277
2278   if (selected_row == -1) {
2279     /* The selected frame didn't pass the filter. */
2280     if (selected_frame == NULL) {
2281       /* That's because there *was* no selected frame.  Make the first
2282          displayed frame the current frame. */
2283       selected_row = 0;
2284     } else {
2285       /* Find the nearest displayed frame to the selected frame (whether
2286          it's before or after that frame) and make that the current frame.
2287          If the next and previous displayed frames are equidistant from the
2288          selected frame, choose the next one. */
2289       g_assert(following_frame == NULL ||
2290                following_frame->num >= selected_frame->num);
2291       g_assert(preceding_frame == NULL ||
2292                preceding_frame->num <= selected_frame->num);
2293       if (following_frame == NULL) {
2294         /* No frame after the selected frame passed the filter, so we
2295            have to select the last displayed frame before the selected
2296            frame. */
2297         selected_row = preceding_row;
2298       } else if (preceding_frame == NULL) {
2299         /* No frame before the selected frame passed the filter, so we
2300            have to select the first displayed frame after the selected
2301            frame. */
2302         selected_row = following_row;
2303       } else {
2304         /* Frames before and after the selected frame passed the filter, so
2305            we'll select the previous frame */
2306         selected_row = preceding_row;
2307       }
2308     }
2309   }
2310
2311   if (selected_row == -1) {
2312     /* There are no frames displayed at all. */
2313     cf_unselect_packet(cf);
2314   } else {
2315     /* Either the frame that was selected passed the filter, or we've
2316        found the nearest displayed frame to that frame.  Select it, make
2317        it the focus row, and make it visible. */
2318     if (selected_row == 0) {
2319       /* Set to invalid to force update of packet list and packet details */
2320       cf->current_row = -1;
2321     }
2322     packet_list_set_selected_row(selected_row);
2323   }
2324
2325   /* Cleanup and release all dfilter resources */
2326   dfilter_free(dfcode);
2327 }
2328 #endif /* NEW_PACKET_LIST */
2329
2330 /*
2331  * Scan trough all frame data and recalculate the ref time
2332  * without rereading the file.
2333  * XXX - do we need a progres bar or is this fast enough?
2334  */
2335 #ifdef NEW_PACKET_LIST
2336 static void
2337 ref_time_packets(capture_file *cf)
2338 {
2339   frame_data *fdata;
2340
2341   nstime_set_unset(&first_ts);
2342   nstime_set_unset(&prev_dis_ts);
2343   nstime_set_unset(&prev_cap_ts);
2344   cum_bytes = 0;
2345
2346   for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
2347     /* just add some value here until we know if it is being displayed or not */
2348     fdata->cum_bytes = cum_bytes + fdata->pkt_len;
2349
2350     /* If we don't have the time stamp of the first packet in the
2351      capture, it's because this is the first packet.  Save the time
2352      stamp of this packet as the time stamp of the first packet. */
2353     if (nstime_is_unset(&first_ts)) {
2354         first_ts  = fdata->abs_ts;
2355     }
2356       /* if this frames is marked as a reference time frame, reset
2357         firstsec and firstusec to this frame */
2358     if(fdata->flags.ref_time){
2359     first_ts = fdata->abs_ts;
2360     }
2361
2362     /* If we don't have the time stamp of the previous displayed packet,
2363      it's because this is the first displayed packet.  Save the time
2364      stamp of this packet as the time stamp of the previous displayed
2365      packet. */
2366     if (nstime_is_unset(&prev_dis_ts)) {
2367         prev_dis_ts = fdata->abs_ts;
2368     }
2369
2370     /* Get the time elapsed between the first packet and this packet. */
2371     nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
2372
2373     /* If it's greater than the current elapsed time, set the elapsed time
2374      to it (we check for "greater than" so as not to be confused by
2375      time moving backwards). */
2376     if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
2377         || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
2378         cf->elapsed_time = fdata->rel_ts;
2379     }
2380
2381     /* Get the time elapsed between the previous displayed packet and
2382      this packet. */
2383     nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
2384
2385     if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
2386         /* This frame either passed the display filter list or is marked as
2387         a time reference frame.  All time reference frames are displayed
2388         even if they dont pass the display filter */
2389         if(fdata->flags.ref_time){
2390             /* if this was a TIME REF frame we should reset the cul bytes field */
2391             cum_bytes = fdata->pkt_len;
2392             fdata->cum_bytes =  cum_bytes;
2393         } else {
2394             /* increase cum_bytes with this packets length */
2395             cum_bytes += fdata->pkt_len;
2396         }
2397     }
2398   }
2399 }
2400 #endif
2401
2402 typedef enum {
2403   PSP_FINISHED,
2404   PSP_STOPPED,
2405   PSP_FAILED
2406 } psp_return_t;
2407
2408 static psp_return_t
2409 process_specified_packets(capture_file *cf, packet_range_t *range,
2410     const char *string1, const char *string2, gboolean terminate_is_stop,
2411     gboolean (*callback)(capture_file *, frame_data *,
2412                          union wtap_pseudo_header *, const guint8 *, void *),
2413     void *callback_args)
2414 {
2415   frame_data *fdata;
2416   int         err;
2417   gchar      *err_info;
2418   union wtap_pseudo_header pseudo_header;
2419   guint8      pd[WTAP_MAX_PACKET_SIZE+1];
2420   psp_return_t ret = PSP_FINISHED;
2421
2422   progdlg_t  *progbar = NULL;
2423   int         progbar_count;
2424   float       progbar_val;
2425   gboolean    progbar_stop_flag;
2426   GTimeVal    progbar_start_time;
2427   gchar       progbar_status_str[100];
2428   int         progbar_nextstep;
2429   int         progbar_quantum;
2430   range_process_e process_this;
2431
2432   /* Update the progress bar when it gets to this value. */
2433   progbar_nextstep = 0;
2434   /* When we reach the value that triggers a progress bar update,
2435      bump that value by this amount. */
2436   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2437   /* Count of packets at which we've looked. */
2438   progbar_count = 0;
2439   /* Progress so far. */
2440   progbar_val = 0.0f;
2441
2442   progbar_stop_flag = FALSE;
2443   g_get_current_time(&progbar_start_time);
2444
2445   packet_range_process_init(range);
2446
2447   /* Iterate through the list of packets, printing the packets that
2448      were selected by the current display filter.  */
2449   for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
2450     /* Create the progress bar if necessary.
2451        We check on every iteration of the loop, so that it takes no
2452        longer than the standard time to create it (otherwise, for a
2453        large file, we might take considerably longer than that standard
2454        time in order to get to the next progress bar step). */
2455     if (progbar == NULL)
2456       progbar = delayed_create_progress_dlg(string1, string2,
2457                                             terminate_is_stop,
2458                                             &progbar_stop_flag,
2459                                             &progbar_start_time,
2460                                             progbar_val);
2461
2462     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2463        when we update it, we have to run the GTK+ main loop to get it
2464        to repaint what's pending, and doing so may involve an "ioctl()"
2465        to see if there's any pending input from an X server, and doing
2466        that for every packet can be costly, especially on a big file. */
2467     if (progbar_count >= progbar_nextstep) {
2468       /* let's not divide by zero. I should never be started
2469        * with count == 0, so let's assert that
2470        */
2471       g_assert(cf->count > 0);
2472       progbar_val = (gfloat) progbar_count / cf->count;
2473
2474       if (progbar != NULL) {
2475         g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2476                    "%4u of %u packets", progbar_count, cf->count);
2477         update_progress_dlg(progbar, progbar_val, progbar_status_str);
2478       }
2479
2480       progbar_nextstep += progbar_quantum;
2481     }
2482
2483     if (progbar_stop_flag) {
2484       /* Well, the user decided to abort the operation.  Just stop,
2485          and arrange to return PSP_STOPPED to our caller, so they know
2486          it was stopped explicitly. */
2487       ret = PSP_STOPPED;
2488       break;
2489     }
2490
2491     progbar_count++;
2492
2493     /* do we have to process this packet? */
2494     process_this = packet_range_process_packet(range, fdata);
2495     if (process_this == range_process_next) {
2496         /* this packet uninteresting, continue with next one */
2497         continue;
2498     } else if (process_this == range_processing_finished) {
2499         /* all interesting packets processed, stop the loop */
2500         break;
2501     }
2502
2503     /* Get the packet */
2504     if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
2505                         pd, fdata->cap_len, &err, &err_info)) {
2506       /* Attempt to get the packet failed. */
2507       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2508                     cf_read_error_message(err, err_info), cf->filename);
2509       ret = PSP_FAILED;
2510       break;
2511     }
2512     /* Process the packet */
2513     if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
2514       /* Callback failed.  We assume it reported the error appropriately. */
2515       ret = PSP_FAILED;
2516       break;
2517     }
2518   }
2519
2520   /* We're done printing the packets; destroy the progress bar if
2521      it was created. */
2522   if (progbar != NULL)
2523     destroy_progress_dlg(progbar);
2524
2525   return ret;
2526 }
2527
2528 typedef struct {
2529   gboolean construct_protocol_tree;
2530   column_info *cinfo;
2531 } retap_callback_args_t;
2532
2533 static gboolean
2534 retap_packet(capture_file *cf _U_, frame_data *fdata,
2535              union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2536              void *argsp)
2537 {
2538   retap_callback_args_t *args = argsp;
2539   epan_dissect_t edt;
2540
2541   epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
2542   tap_queue_init(&edt);
2543   epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
2544   tap_push_tapped_queue(&edt);
2545   epan_dissect_cleanup(&edt);
2546
2547   return TRUE;
2548 }
2549
2550 cf_read_status_t
2551 cf_retap_packets(capture_file *cf)
2552 {
2553   packet_range_t range;
2554   retap_callback_args_t callback_args;
2555   gboolean filtering_tap_listeners;
2556   guint tap_flags;
2557
2558   /* Do we have any tap listeners with filters? */
2559   filtering_tap_listeners = have_filtering_tap_listeners();
2560
2561   tap_flags = union_of_tap_listener_flags();
2562
2563   /* If any tap listeners have filters, or require the protocol tree,
2564      construct the protocol tree. */
2565   callback_args.construct_protocol_tree = filtering_tap_listeners ||
2566                                           (tap_flags & TL_REQUIRES_PROTO_TREE);
2567
2568   /* If any tap listeners require the columns, construct them. */
2569   callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2570
2571   /* Reset the tap listeners. */
2572   reset_tap_listeners();
2573
2574   /* Iterate through the list of packets, dissecting all packets and
2575      re-running the taps. */
2576   packet_range_init(&range);
2577   packet_range_process_init(&range);
2578   switch (process_specified_packets(cf, &range, "Recalculating statistics on",
2579                                     "all packets", TRUE, retap_packet,
2580                                     &callback_args)) {
2581   case PSP_FINISHED:
2582     /* Completed successfully. */
2583     return CF_READ_OK;
2584
2585   case PSP_STOPPED:
2586     /* Well, the user decided to abort the refiltering.
2587        Return CF_READ_ABORTED so our caller knows they did that. */
2588     return CF_READ_ABORTED;
2589
2590   case PSP_FAILED:
2591     /* Error while retapping. */
2592     return CF_READ_ERROR;
2593   }
2594
2595   g_assert_not_reached();
2596   return CF_READ_OK;
2597 }
2598
2599 typedef struct {
2600   print_args_t *print_args;
2601   gboolean      print_header_line;
2602   char         *header_line_buf;
2603   int           header_line_buf_len;
2604   gboolean      print_formfeed;
2605   gboolean      print_separator;
2606   char         *line_buf;
2607   int           line_buf_len;
2608   gint         *col_widths;
2609 } print_callback_args_t;
2610
2611 static gboolean
2612 print_packet(capture_file *cf, frame_data *fdata,
2613              union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2614              void *argsp)
2615 {
2616   print_callback_args_t *args = argsp;
2617   epan_dissect_t edt;
2618   int             i;
2619   char           *cp;
2620   int             line_len;
2621   int             column_len;
2622   int             cp_off;
2623   gboolean        proto_tree_needed;
2624   char            bookmark_name[9+10+1];    /* "__frameNNNNNNNNNN__\0" */
2625   char            bookmark_title[6+10+1];   /* "Frame NNNNNNNNNN__\0" */
2626
2627   /* Create the protocol tree, and make it visible, if we're printing
2628      the dissection or the hex data.
2629      XXX - do we need it if we're just printing the hex data? */
2630   proto_tree_needed =
2631       args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
2632   epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2633
2634   /* Fill in the column information if we're printing the summary
2635      information. */
2636   if (args->print_args->print_summary) {
2637     col_custom_prime_edt(&edt, &cf->cinfo);
2638     epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2639     epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2640   } else
2641     epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2642
2643   if (args->print_formfeed) {
2644     if (!new_page(args->print_args->stream))
2645       goto fail;
2646   } else {
2647       if (args->print_separator) {
2648         if (!print_line(args->print_args->stream, 0, ""))
2649           goto fail;
2650       }
2651   }
2652
2653   /*
2654    * We generate bookmarks, if the output format supports them.
2655    * The name is "__frameN__".
2656    */
2657   g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2658
2659   if (args->print_args->print_summary) {
2660     if (args->print_header_line) {
2661       if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2662         goto fail;
2663       args->print_header_line = FALSE;  /* we might not need to print any more */
2664     }
2665     cp = &args->line_buf[0];
2666     line_len = 0;
2667     for (i = 0; i < cf->cinfo.num_cols; i++) {
2668       /* Find the length of the string for this column. */
2669       column_len = (int) strlen(cf->cinfo.col_data[i]);
2670       if (args->col_widths[i] > column_len)
2671          column_len = args->col_widths[i];
2672
2673       /* Make sure there's room in the line buffer for the column; if not,
2674          double its length. */
2675       line_len += column_len + 1;   /* "+1" for space */
2676       if (line_len > args->line_buf_len) {
2677         cp_off = (int) (cp - args->line_buf);
2678         args->line_buf_len = 2 * line_len;
2679         args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
2680         cp = args->line_buf + cp_off;
2681       }
2682
2683       /* Right-justify the packet number column. */
2684       if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2685         g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
2686       else
2687         g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
2688       cp += column_len;
2689       if (i != cf->cinfo.num_cols - 1)
2690         *cp++ = ' ';
2691     }
2692     *cp = '\0';
2693
2694     /*
2695      * Generate a bookmark, using the summary line as the title.
2696      */
2697     if (!print_bookmark(args->print_args->stream, bookmark_name,
2698                         args->line_buf))
2699       goto fail;
2700
2701     if (!print_line(args->print_args->stream, 0, args->line_buf))
2702       goto fail;
2703   } else {
2704     /*
2705      * Generate a bookmark, using "Frame N" as the title, as we're not
2706      * printing the summary line.
2707      */
2708     g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2709     if (!print_bookmark(args->print_args->stream, bookmark_name,
2710                         bookmark_title))
2711       goto fail;
2712   } /* if (print_summary) */
2713
2714   if (args->print_args->print_dissections != print_dissections_none) {
2715     if (args->print_args->print_summary) {
2716       /* Separate the summary line from the tree with a blank line. */
2717       if (!print_line(args->print_args->stream, 0, ""))
2718         goto fail;
2719     }
2720
2721     /* Print the information in that tree. */
2722     if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
2723       goto fail;
2724
2725     /* Print a blank line if we print anything after this (aka more than one packet). */
2726     args->print_separator = TRUE;
2727
2728     /* Print a header line if we print any more packet summaries */
2729     args->print_header_line = TRUE;
2730   }
2731
2732   if (args->print_args->print_hex) {
2733     /* Print the full packet data as hex. */
2734     if (!print_hex_data(args->print_args->stream, &edt))
2735       goto fail;
2736
2737     /* Print a blank line if we print anything after this (aka more than one packet). */
2738     args->print_separator = TRUE;
2739
2740     /* Print a header line if we print any more packet summaries */
2741     args->print_header_line = TRUE;
2742   } /* if (args->print_args->print_dissections != print_dissections_none) */
2743
2744   epan_dissect_cleanup(&edt);
2745
2746   /* do we want to have a formfeed between each packet from now on? */
2747   if(args->print_args->print_formfeed) {
2748     args->print_formfeed = TRUE;
2749   }
2750
2751   return TRUE;
2752
2753 fail:
2754   epan_dissect_cleanup(&edt);
2755   return FALSE;
2756 }
2757
2758 cf_print_status_t
2759 cf_print_packets(capture_file *cf, print_args_t *print_args)
2760 {
2761   int         i;
2762   print_callback_args_t callback_args;
2763   gint        data_width;
2764   char        *cp;
2765   int         cp_off;
2766   int         column_len;
2767   int         line_len;
2768   psp_return_t ret;
2769
2770   callback_args.print_args = print_args;
2771   callback_args.print_header_line = TRUE;
2772   callback_args.header_line_buf = NULL;
2773   callback_args.header_line_buf_len = 256;
2774   callback_args.print_formfeed = FALSE;
2775   callback_args.print_separator = FALSE;
2776   callback_args.line_buf = NULL;
2777   callback_args.line_buf_len = 256;
2778   callback_args.col_widths = NULL;
2779
2780   if (!print_preamble(print_args->stream, cf->filename)) {
2781     destroy_print_stream(print_args->stream);
2782     return CF_PRINT_WRITE_ERROR;
2783   }
2784
2785   if (print_args->print_summary) {
2786     /* We're printing packet summaries.  Allocate the header line buffer
2787        and get the column widths. */
2788     callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2789
2790     /* Find the widths for each of the columns - maximum of the
2791        width of the title and the width of the data - and construct
2792        a buffer with a line containing the column titles. */
2793     callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2794     cp = &callback_args.header_line_buf[0];
2795     line_len = 0;
2796     for (i = 0; i < cf->cinfo.num_cols; i++) {
2797       /* Don't pad the last column. */
2798       if (i == cf->cinfo.num_cols - 1)
2799         callback_args.col_widths[i] = 0;
2800       else {
2801         callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
2802         data_width = get_column_char_width(get_column_format(i));
2803         if (data_width > callback_args.col_widths[i])
2804           callback_args.col_widths[i] = data_width;
2805       }
2806
2807       /* Find the length of the string for this column. */
2808       column_len = (int) strlen(cf->cinfo.col_title[i]);
2809       if (callback_args.col_widths[i] > column_len)
2810         column_len = callback_args.col_widths[i];
2811
2812       /* Make sure there's room in the line buffer for the column; if not,
2813          double its length. */
2814       line_len += column_len + 1;   /* "+1" for space */
2815       if (line_len > callback_args.header_line_buf_len) {
2816         cp_off = (int) (cp - callback_args.header_line_buf);
2817         callback_args.header_line_buf_len = 2 * line_len;
2818         callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2819                                                   callback_args.header_line_buf_len + 1);
2820         cp = callback_args.header_line_buf + cp_off;
2821       }
2822
2823       /* Right-justify the packet number column. */
2824 /*      if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2825         g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2826       else*/
2827       g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2828       cp += column_len;
2829       if (i != cf->cinfo.num_cols - 1)
2830         *cp++ = ' ';
2831     }
2832     *cp = '\0';
2833
2834     /* Now start out the main line buffer with the same length as the
2835        header line buffer. */
2836     callback_args.line_buf_len = callback_args.header_line_buf_len;
2837     callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2838   } /* if (print_summary) */
2839
2840   /* Iterate through the list of packets, printing the packets we were
2841      told to print. */
2842   ret = process_specified_packets(cf, &print_args->range, "Printing",
2843                                   "selected packets", TRUE, print_packet,
2844                                   &callback_args);
2845
2846   g_free(callback_args.header_line_buf);
2847   g_free(callback_args.line_buf);
2848   g_free(callback_args.col_widths);
2849
2850   switch (ret) {
2851
2852   case PSP_FINISHED:
2853     /* Completed successfully. */
2854     break;
2855
2856   case PSP_STOPPED:
2857     /* Well, the user decided to abort the printing.
2858
2859        XXX - note that what got generated before they did that
2860        will get printed if we're piping to a print program; we'd
2861        have to write to a file and then hand that to the print
2862        program to make it actually not print anything. */
2863     break;
2864
2865   case PSP_FAILED:
2866     /* Error while printing.
2867
2868        XXX - note that what got generated before they did that
2869        will get printed if we're piping to a print program; we'd
2870        have to write to a file and then hand that to the print
2871        program to make it actually not print anything. */
2872     destroy_print_stream(print_args->stream);
2873     return CF_PRINT_WRITE_ERROR;
2874   }
2875
2876   if (!print_finale(print_args->stream)) {
2877     destroy_print_stream(print_args->stream);
2878     return CF_PRINT_WRITE_ERROR;
2879   }
2880
2881   if (!destroy_print_stream(print_args->stream))
2882     return CF_PRINT_WRITE_ERROR;
2883
2884   return CF_PRINT_OK;
2885 }
2886
2887 static gboolean
2888 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2889                   union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2890           void *argsp)
2891 {
2892   FILE *fh = argsp;
2893   epan_dissect_t edt;
2894
2895   /* Create the protocol tree, but don't fill in the column information. */
2896   epan_dissect_init(&edt, TRUE, TRUE);
2897   epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
2898
2899   /* Write out the information in that tree. */
2900   proto_tree_write_pdml(&edt, fh);
2901
2902   epan_dissect_cleanup(&edt);
2903
2904   return !ferror(fh);
2905 }
2906
2907 cf_print_status_t
2908 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2909 {
2910   FILE        *fh;
2911   psp_return_t ret;
2912
2913   fh = ws_fopen(print_args->file, "w");
2914   if (fh == NULL)
2915     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2916
2917   write_pdml_preamble(fh);
2918   if (ferror(fh)) {
2919     fclose(fh);
2920     return CF_PRINT_WRITE_ERROR;
2921   }
2922
2923   /* Iterate through the list of packets, printing the packets we were
2924      told to print. */
2925   ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2926                                   "selected packets", TRUE,
2927                                   write_pdml_packet, fh);
2928
2929   switch (ret) {
2930
2931   case PSP_FINISHED:
2932     /* Completed successfully. */
2933     break;
2934
2935   case PSP_STOPPED:
2936     /* Well, the user decided to abort the printing. */
2937     break;
2938
2939   case PSP_FAILED:
2940     /* Error while printing. */
2941     fclose(fh);
2942     return CF_PRINT_WRITE_ERROR;
2943   }
2944
2945   write_pdml_finale(fh);
2946   if (ferror(fh)) {
2947     fclose(fh);
2948     return CF_PRINT_WRITE_ERROR;
2949   }
2950
2951   /* XXX - check for an error */
2952   fclose(fh);
2953
2954   return CF_PRINT_OK;
2955 }
2956
2957 static gboolean
2958 write_psml_packet(capture_file *cf, frame_data *fdata,
2959                   union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2960           void *argsp)
2961 {
2962   FILE *fh = argsp;
2963   epan_dissect_t edt;
2964   gboolean proto_tree_needed;
2965
2966   /* Fill in the column information, only create the protocol tree
2967      if having custom columns. */
2968   proto_tree_needed = have_custom_cols(&cf->cinfo);
2969   epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
2970   col_custom_prime_edt(&edt, &cf->cinfo);
2971   epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
2972   epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
2973
2974   /* Write out the information in that tree. */
2975   proto_tree_write_psml(&edt, fh);
2976
2977   epan_dissect_cleanup(&edt);
2978
2979   return !ferror(fh);
2980 }
2981
2982 cf_print_status_t
2983 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2984 {
2985   FILE        *fh;
2986   psp_return_t ret;
2987
2988   fh = ws_fopen(print_args->file, "w");
2989   if (fh == NULL)
2990     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2991
2992   write_psml_preamble(fh);
2993   if (ferror(fh)) {
2994     fclose(fh);
2995     return CF_PRINT_WRITE_ERROR;
2996   }
2997
2998   /* Iterate through the list of packets, printing the packets we were
2999      told to print. */
3000   ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
3001                                   "selected packets", TRUE,
3002                                   write_psml_packet, fh);
3003
3004   switch (ret) {
3005
3006   case PSP_FINISHED:
3007     /* Completed successfully. */
3008     break;
3009
3010   case PSP_STOPPED:
3011     /* Well, the user decided to abort the printing. */
3012     break;
3013
3014   case PSP_FAILED:
3015     /* Error while printing. */
3016     fclose(fh);
3017     return CF_PRINT_WRITE_ERROR;
3018   }
3019
3020   write_psml_finale(fh);
3021   if (ferror(fh)) {
3022     fclose(fh);
3023     return CF_PRINT_WRITE_ERROR;
3024   }
3025
3026   /* XXX - check for an error */
3027   fclose(fh);
3028
3029   return CF_PRINT_OK;
3030 }
3031
3032 static gboolean
3033 write_csv_packet(capture_file *cf, frame_data *fdata,
3034                  union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3035                  void *argsp)
3036 {
3037   FILE *fh = argsp;
3038   epan_dissect_t edt;
3039   gboolean proto_tree_needed;
3040
3041   /* Fill in the column information, only create the protocol tree
3042      if having custom columns. */
3043   proto_tree_needed = have_custom_cols(&cf->cinfo);
3044   epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
3045   col_custom_prime_edt(&edt, &cf->cinfo);
3046   epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
3047   epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
3048
3049   /* Write out the information in that tree. */
3050   proto_tree_write_csv(&edt, fh);
3051
3052   epan_dissect_cleanup(&edt);
3053
3054   return !ferror(fh);
3055 }
3056
3057 cf_print_status_t
3058 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
3059 {
3060   FILE        *fh;
3061   psp_return_t ret;
3062
3063   fh = ws_fopen(print_args->file, "w");
3064   if (fh == NULL)
3065     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3066
3067   write_csv_preamble(fh);
3068   if (ferror(fh)) {
3069     fclose(fh);
3070     return CF_PRINT_WRITE_ERROR;
3071   }
3072
3073   /* Iterate through the list of packets, printing the packets we were
3074      told to print. */
3075   ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
3076                                   "selected packets", TRUE,
3077                                   write_csv_packet, fh);
3078
3079   switch (ret) {
3080
3081   case PSP_FINISHED:
3082     /* Completed successfully. */
3083     break;
3084
3085   case PSP_STOPPED:
3086     /* Well, the user decided to abort the printing. */
3087     break;
3088
3089   case PSP_FAILED:
3090     /* Error while printing. */
3091     fclose(fh);
3092     return CF_PRINT_WRITE_ERROR;
3093   }
3094
3095   write_csv_finale(fh);
3096   if (ferror(fh)) {
3097     fclose(fh);
3098     return CF_PRINT_WRITE_ERROR;
3099   }
3100
3101   /* XXX - check for an error */
3102   fclose(fh);
3103
3104   return CF_PRINT_OK;
3105 }
3106
3107 static gboolean
3108 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
3109              union wtap_pseudo_header *pseudo_header _U_,
3110              const guint8 *pd, void *argsp)
3111 {
3112   FILE *fh = argsp;
3113
3114   proto_tree_write_carrays(pd, fdata->cap_len, fdata->num, fh);
3115   return !ferror(fh);
3116 }
3117
3118 cf_print_status_t
3119 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
3120 {
3121   FILE        *fh;
3122   psp_return_t ret;
3123
3124   fh = ws_fopen(print_args->file, "w");
3125
3126   if (fh == NULL)
3127     return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3128
3129   write_carrays_preamble(fh);
3130
3131   if (ferror(fh)) {
3132     fclose(fh);
3133     return CF_PRINT_WRITE_ERROR;
3134   }
3135
3136   /* Iterate through the list of packets, printing the packets we were
3137      told to print. */
3138   ret = process_specified_packets(cf, &print_args->range,
3139                   "Writing C Arrays",
3140                   "selected packets", TRUE,
3141                                   write_carrays_packet, fh);
3142   switch (ret) {
3143   case PSP_FINISHED:
3144     /* Completed successfully. */
3145     break;
3146   case PSP_STOPPED:
3147     /* Well, the user decided to abort the printing. */
3148     break;
3149   case PSP_FAILED:
3150     /* Error while printing. */
3151     fclose(fh);
3152     return CF_PRINT_WRITE_ERROR;
3153   }
3154
3155   write_carrays_finale(fh);
3156
3157   if (ferror(fh)) {
3158     fclose(fh);
3159     return CF_PRINT_WRITE_ERROR;
3160   }
3161
3162   fclose(fh);
3163   return CF_PRINT_OK;
3164 }
3165
3166 #ifndef NEW_PACKET_LIST /* This function is not needed with the new packet list */
3167
3168 /* Scan through the packet list and change all columns that use the
3169    "command-line-specified" time stamp format to use the current
3170    value of that format. */
3171 void
3172 cf_change_time_formats(capture_file *cf)
3173 {
3174   int         i;
3175   frame_data *fdata;
3176   progdlg_t  *progbar = NULL;
3177   gboolean    stop_flag;
3178   int         count;
3179   int         row;
3180   float       progbar_val;
3181   GTimeVal    start_time;
3182   gchar       status_str[100];
3183   int         progbar_nextstep;
3184   int         progbar_quantum;
3185   gboolean    sorted_by_frame_column;
3186
3187   /* Adjust timestamp precision if auto is selected */
3188   cf_timestamp_auto_precision(cf);
3189
3190   /* Are there any columns with time stamps in the "command-line-specified"
3191      format?
3192
3193      XXX - we have to force the "column is writable" flag on, as it
3194      might be off from the last frame that was dissected. */
3195   col_set_writable(&cf->cinfo, TRUE);
3196   if (!check_col(&cf->cinfo, COL_CLS_TIME) &&
3197       !check_col(&cf->cinfo, COL_ABS_TIME) &&
3198       !check_col(&cf->cinfo, COL_ABS_DATE_TIME) &&
3199       !check_col(&cf->cinfo, COL_REL_TIME) &&
3200       !check_col(&cf->cinfo, COL_DELTA_TIME) &&
3201       !check_col(&cf->cinfo, COL_DELTA_TIME_DIS)) {
3202     /* No, there aren't any columns in that format, so we have no work
3203        to do. */
3204     return;
3205   }
3206
3207   /* Freeze the packet list while we redo it, so we don't get any
3208      screen updates while it happens. */
3209   packet_list_freeze();
3210
3211   /* Update the progress bar when it gets to this value. */
3212   progbar_nextstep = 0;
3213   /* When we reach the value that triggers a progress bar update,
3214      bump that value by this amount. */
3215   progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3216   /* Count of packets at which we've looked. */
3217   count = 0;
3218   /* Progress so far. */
3219   progbar_val = 0.0f;
3220
3221   /*  If the rows are currently sorted by the frame column then we know
3222    *  the row number of each packet: it's the row number of the previously
3223    *  displayed packet + 1.
3224    *
3225    *  Otherwise, if the display is sorted by a different column then we have
3226    *  to use the O(N) packet_list_find_row_from_data() (thus making the job
3227    *  of changing the time display format O(N**2)).
3228    *
3229    *  (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
3230    *  the row number and walks that many elements down the clist to find
3231    *  the appropriate element.)
3232    */
3233   sorted_by_frame_column = FALSE;
3234   for (i = 0; i < cf->cinfo.num_cols; i++) {
3235     if (cf->cinfo.col_fmt[i] == COL_NUMBER)
3236     {
3237       sorted_by_frame_column = (i == packet_list_get_sort_column());
3238       break;
3239     }
3240   }
3241
3242   stop_flag = FALSE;
3243   g_get_current_time(&start_time);
3244
3245   /* Iterate through the list of packets, checking whether the packet
3246      is in a row of the summary list and, if so, whether there are
3247      any columns that show the time in the "command-line-specified"
3248      format and, if so, update that row. */
3249   for (fdata = cf->plist_start, row = -1; fdata != NULL; fdata = fdata->next) {
3250     /* Create the progress bar if necessary.
3251        We check on every iteration of the loop, so that it takes no
3252        longer than the standard time to create it (otherwise, for a
3253        large file, we might take considerably longer than that standard
3254        time in order to get to the next progress bar step). */
3255     if (progbar == NULL)
3256       progbar = delayed_create_progress_dlg("Changing", "time display",
3257         TRUE, &stop_flag, &start_time, progbar_val);
3258
3259     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3260        when we update it, we have to run the GTK+ main loop to get it
3261        to repaint what's pending, and doing so may involve an "ioctl()"
3262        to see if there's any pending input from an X server, and doing
3263        that for every packet can be costly, especially on a big file. */
3264     if (count >= progbar_nextstep) {
3265       /* let's not divide by zero. I should never be started
3266        * with count == 0, so let's assert that
3267        */
3268       g_assert(cf->count > 0);
3269
3270       progbar_val = (gfloat) count / cf->count;
3271
3272       if (progbar != NULL) {
3273         g_snprintf(status_str, sizeof(status_str),
3274                    "%4u of %u packets", count, cf->count);
3275         update_progress_dlg(progbar, progbar_val, status_str);
3276       }
3277
3278       progbar_nextstep += progbar_quantum;
3279     }
3280
3281     if (stop_flag) {
3282       /* Well, the user decided to abort the redisplay.  Just stop.
3283
3284          XXX - this leaves the time field in the old format in
3285      frames we haven't yet processed.  So it goes; should we
3286      simply not offer them the option of stopping? */
3287       break;
3288     }
3289
3290     count++;
3291
3292     /* Find what row this packet is in. */
3293     if (!sorted_by_frame_column) {
3294       /* This function is O(N), so we try to avoid using it... */
3295       row = packet_list_find_row_from_data(fdata);
3296     } else {
3297       /* ...which we do by maintaining a count of packets that are
3298          being displayed (i.e., that have passed the display filter),
3299          and using the current value of that count as the row number
3300          (which is why we can only do it when the display is sorted
3301          by the frame number). */
3302       if (fdata->flags.passed_dfilter)
3303         row++;
3304       else
3305         continue;
3306     }
3307
3308     if (row != -1) {
3309       /* This packet is in the summary list, on row "row". */
3310
3311       for (i = 0; i < cf->cinfo.num_cols; i++) {
3312         if (col_has_time_fmt(&cf->cinfo, i)) {
3313           /* This is one of the columns that shows the time in
3314              "command-line-specified" format; update it. */
3315           cf->cinfo.col_buf[i][0] = '\0';
3316           col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
3317           packet_list_set_text(row, i, cf->cinfo.col_data[i]);
3318         }
3319       }
3320     }
3321   }
3322
3323   /* We're done redisplaying the packets; destroy the progress bar if it
3324      was created. */
3325   if (progbar != NULL)
3326     destroy_progress_dlg(progbar);
3327
3328   /* Set the column widths of those columns that show the time in
3329      "command-line-specified" format. */
3330   for (i = 0; i < cf->cinfo.num_cols; i++) {
3331     if (col_has_time_fmt(&cf->cinfo, i)) {
3332       packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
3333     }
3334   }
3335
3336   /* Unfreeze the packet list. */
3337   packet_list_thaw();
3338 }
3339 #endif /* NEW_PACKET_LIST */
3340
3341
3342 typedef struct {
3343     const char  *string;
3344     size_t      string_len;
3345     capture_file    *cf;
3346     gboolean    frame_matched;
3347 } match_data;
3348
3349 gboolean
3350 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
3351 {
3352   match_data        mdata;
3353
3354   mdata.string = string;
3355   mdata.string_len = strlen(string);
3356   return find_packet(cf, match_protocol_tree, &mdata);
3357 }
3358
3359 static gboolean
3360 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3361 {
3362   match_data        *mdata = criterion;
3363   epan_dissect_t    edt;
3364
3365   /* Construct the protocol tree, including the displayed text */
3366   epan_dissect_init(&edt, TRUE, TRUE);
3367   /* We don't need the column information */
3368   epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3369
3370   /* Iterate through all the nodes, seeing if they have text that matches. */
3371   mdata->cf = cf;
3372   mdata->frame_matched = FALSE;
3373   proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3374   epan_dissect_cleanup(&edt);
3375   return mdata->frame_matched;
3376 }
3377
3378 static void
3379 match_subtree_text(proto_node *node, gpointer data)
3380 {
3381   match_data    *mdata = (match_data*) data;
3382   const gchar   *string = mdata->string;
3383   size_t    string_len = mdata->string_len;
3384   capture_file  *cf = mdata->cf;
3385   field_info    *fi = PNODE_FINFO(node);
3386   gchar     label_str[ITEM_LABEL_LENGTH];
3387   gchar     *label_ptr;
3388   size_t    label_len;
3389   guint32   i;
3390   guint8    c_char;
3391   size_t    c_match = 0;
3392
3393   g_assert(fi && "dissection with an invisible proto tree?");
3394
3395   if (mdata->frame_matched) {
3396     /* We already had a match; don't bother doing any more work. */
3397     return;
3398   }
3399
3400   /* Don't match invisible entries. */
3401   if (PROTO_ITEM_IS_HIDDEN(node))
3402     return;
3403
3404   /* was a free format label produced? */
3405   if (fi->rep) {
3406     label_ptr = fi->rep->representation;
3407   } else {
3408     /* no, make a generic label */
3409     label_ptr = label_str;
3410     proto_item_fill_label(fi, label_str);
3411   }
3412
3413   /* Does that label match? */
3414   label_len = strlen(label_ptr);
3415   for (i = 0; i < label_len; i++) {
3416     c_char = label_ptr[i];
3417     if (cf->case_type)
3418       c_char = toupper(c_char);
3419     if (c_char == string[c_match]) {
3420       c_match++;
3421       if (c_match == string_len) {
3422     /* No need to look further; we have a match */
3423     mdata->frame_matched = TRUE;
3424     return;
3425       }
3426     } else
3427       c_match = 0;
3428   }
3429
3430   /* Recurse into the subtree, if it exists */
3431   if (node->first_child != NULL)
3432     proto_tree_children_foreach(node, match_subtree_text, mdata);
3433 }
3434
3435 gboolean
3436 cf_find_packet_summary_line(capture_file *cf, const char *string)
3437 {
3438   match_data        mdata;
3439
3440   mdata.string = string;
3441   mdata.string_len = strlen(string);
3442   return find_packet(cf, match_summary_line, &mdata);
3443 }
3444
3445 static gboolean
3446 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3447 {
3448   match_data        *mdata = criterion;
3449   const gchar       *string = mdata->string;
3450   size_t        string_len = mdata->string_len;
3451   epan_dissect_t    edt;
3452   const char        *info_column;
3453   size_t        info_column_len;
3454   gboolean      frame_matched = FALSE;
3455   gint          colx;
3456   guint32       i;
3457   guint8        c_char;
3458   size_t        c_match = 0;
3459
3460   /* Don't bother constructing the protocol tree */
3461   epan_dissect_init(&edt, FALSE, FALSE);
3462   /* Get the column information */
3463   epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
3464
3465   /* Find the Info column */
3466   for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3467     if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3468       /* Found it.  See if we match. */
3469       info_column = edt.pi.cinfo->col_data[colx];
3470       info_column_len = strlen(info_column);
3471       for (i = 0; i < info_column_len; i++) {
3472     c_char = info_column[i];
3473     if (cf->case_type)
3474       c_char = toupper(c_char);
3475     if (c_char == string[c_match]) {
3476       c_match++;
3477       if (c_match == string_len) {
3478         frame_matched = TRUE;
3479         break;
3480       }
3481     } else
3482       c_match = 0;
3483       }
3484       break;
3485     }
3486   }
3487   epan_dissect_cleanup(&edt);
3488   return frame_matched;
3489 }
3490
3491 typedef struct {
3492     const guint8 *data;
3493     size_t data_len;
3494 } cbs_t;    /* "Counted byte string" */
3495
3496 gboolean
3497 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
3498 {
3499   cbs_t info;
3500
3501   info.data = string;
3502   info.data_len = string_size;
3503
3504   /* String or hex search? */
3505   if (cf->string) {
3506     /* String search - what type of string? */
3507     switch (cf->scs_type) {
3508
3509     case SCS_ASCII_AND_UNICODE:
3510       return find_packet(cf, match_ascii_and_unicode, &info);
3511
3512     case SCS_ASCII:
3513       return find_packet(cf, match_ascii, &info);
3514
3515     case SCS_UNICODE:
3516       return find_packet(cf, match_unicode, &info);
3517
3518     default:
3519       g_assert_not_reached();
3520       return FALSE;
3521     }
3522   } else
3523     return find_packet(cf, match_binary, &info);
3524 }
3525
3526 static gboolean
3527 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3528 {
3529   cbs_t     *info = criterion;
3530   const guint8  *ascii_text = info->data;
3531   size_t    textlen = info->data_len;
3532   gboolean  frame_matched;
3533   guint32   buf_len;
3534   guint32   i;
3535   guint8    c_char;
3536   size_t    c_match = 0;
3537
3538   frame_matched = FALSE;
3539   buf_len = fdata->pkt_len;
3540   for (i = 0; i < buf_len; i++) {
3541     c_char = cf->pd[i];
3542     if (cf->case_type)
3543       c_char = toupper(c_char);
3544     if (c_char != 0) {
3545       if (c_char == ascii_text[c_match]) {
3546     c_match++;
3547     if (c_match == textlen) {
3548       frame_matched = TRUE;
3549       cf->search_pos = i; /* Save the position of the last character
3550                    for highlighting the field. */
3551       break;
3552     }
3553       } else
3554     c_match = 0;
3555     }
3556   }
3557   return frame_matched;
3558 }
3559
3560 static gboolean
3561 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
3562 {
3563   cbs_t     *info = criterion;
3564   const guint8  *ascii_text = info->data;
3565   size_t    textlen = info->data_len;
3566   gboolean  frame_matched;
3567   guint32   buf_len;
3568   guint32   i;
3569   guint8    c_char;
3570   size_t    c_match = 0;
3571
3572   frame_matched = FALSE;
3573   buf_len = fdata->pkt_len;
3574   for (i = 0; i < buf_len; i++) {
3575     c_char = cf->pd[i];
3576     if (cf->case_type)
3577       c_char = toupper(c_char);
3578     if (c_char == ascii_text[c_match]) {
3579       c_match++;
3580       if (c_match == textlen) {
3581     frame_matched = TRUE;
3582     cf->search_pos = i; /* Save the position of the last character
3583                    for highlighting the field. */
3584     break;
3585       }
3586     } else
3587       c_match = 0;
3588   }
3589   return frame_matched;
3590 }
3591
3592 static gboolean
3593 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
3594 {
3595   cbs_t     *info = criterion;
3596   const guint8  *ascii_text = info->data;
3597   size_t    textlen = info->data_len;
3598   gboolean  frame_matched;
3599   guint32   buf_len;
3600   guint32   i;
3601   guint8    c_char;
3602   size_t    c_match = 0;
3603
3604   frame_matched = FALSE;
3605   buf_len = fdata->pkt_len;
3606   for (i = 0; i < buf_len; i++) {
3607     c_char = cf->pd[i];
3608     if (cf->case_type)
3609       c_char = toupper(c_char);
3610     if (c_char == ascii_text[c_match]) {
3611       c_match++;
3612       i++;
3613       if (c_match == textlen) {
3614     frame_matched = TRUE;
3615     cf->search_pos = i; /* Save the position of the last character
3616                    for highlighting the field. */
3617     break;
3618       }
3619     } else
3620       c_match = 0;
3621   }
3622   return frame_matched;
3623 }
3624
3625 static gboolean
3626 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3627 {
3628   cbs_t     *info = criterion;
3629   const guint8  *binary_data = info->data;
3630   size_t    datalen = info->data_len;
3631   gboolean  frame_matched;
3632   guint32   buf_len;
3633   guint32   i;
3634   size_t    c_match = 0;
3635
3636   frame_matched = FALSE;
3637   buf_len = fdata->pkt_len;
3638   for (i = 0; i < buf_len; i++) {
3639     if (cf->pd[i] == binary_data[c_match]) {
3640       c_match++;
3641       if (c_match == datalen) {
3642     frame_matched = TRUE;
3643     cf->search_pos = i; /* Save the position of the last character
3644                    for highlighting the field. */
3645     break;
3646       }
3647     } else
3648       c_match = 0;
3649   }
3650   return frame_matched;
3651 }
3652
3653 gboolean
3654 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
3655 {
3656   return find_packet(cf, match_dfilter, sfcode);
3657 }
3658
3659 static gboolean
3660 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3661 {
3662   dfilter_t     *sfcode = criterion;
3663   epan_dissect_t    edt;
3664   gboolean      frame_matched;
3665
3666   epan_dissect_init(&edt, TRUE, FALSE);
3667   epan_dissect_prime_dfilter(&edt, sfcode);
3668   epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
3669   frame_matched = dfilter_apply_edt(sfcode, &edt);
3670   epan_dissect_cleanup(&edt);
3671   return frame_matched;
3672 }
3673
3674 static gboolean
3675 find_packet(capture_file *cf,
3676             gboolean (*match_function)(capture_file *, frame_data *, void *),
3677             void *criterion)
3678 {
3679   frame_data *start_fd;
3680   frame_data *fdata;
3681   frame_data *new_fd = NULL;
3682   progdlg_t  *progbar = NULL;
3683   gboolean    stop_flag;
3684   int         count;
3685   int         err;
3686   gchar      *err_info;
3687   int         row;
3688   float       progbar_val;
3689   GTimeVal    start_time;
3690   gchar       status_str[100];
3691   int         progbar_nextstep;
3692   int         progbar_quantum;
3693   const char *title;
3694
3695   start_fd = cf->current_frame;
3696   if (start_fd != NULL)  {
3697     /* Iterate through the list of packets, starting at the packet we've
3698        picked, calling a routine to run the filter on the packet, see if
3699        it matches, and stop if so.  */
3700     count = 0;
3701     fdata = start_fd;
3702
3703     /* Update the progress bar when it gets to this value. */
3704     progbar_nextstep = 0;
3705     /* When we reach the value that triggers a progress bar update,
3706        bump that value by this amount. */
3707     progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3708     /* Progress so far. */
3709     progbar_val = 0.0f;
3710
3711     stop_flag = FALSE;
3712     g_get_current_time(&start_time);
3713
3714     fdata = start_fd;
3715     title = cf->sfilter?cf->sfilter:"";
3716     for (;;) {
3717       /* Create the progress bar if necessary.
3718          We check on every iteration of the loop, so that it takes no
3719          longer than the standard time to create it (otherwise, for a
3720          large file, we might take considerably longer than that standard
3721          time in order to get to the next progress bar step). */
3722       if (progbar == NULL)
3723          progbar = delayed_create_progress_dlg("Searching", title,
3724            FALSE, &stop_flag, &start_time, progbar_val);
3725
3726       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3727          when we update it, we have to run the GTK+ main loop to get it
3728          to repaint what's pending, and doing so may involve an "ioctl()"
3729          to see if there's any pending input from an X server, and doing
3730          that for every packet can be costly, especially on a big file. */
3731       if (count >= progbar_nextstep) {
3732         /* let's not divide by zero. I should never be started
3733          * with count == 0, so let's assert that
3734          */
3735         g_assert(cf->count > 0);
3736
3737         progbar_val = (gfloat) count / cf->count;
3738
3739         if (progbar != NULL) {
3740           g_snprintf(status_str, sizeof(status_str),
3741                      "%4u of %u packets", count, cf->count);
3742           update_progress_dlg(progbar, progbar_val, status_str);
3743         }
3744
3745         progbar_nextstep += progbar_quantum;
3746       }
3747
3748       if (stop_flag) {
3749         /* Well, the user decided to abort the search.  Go back to the
3750            frame where we started. */
3751         new_fd = start_fd;
3752         break;
3753       }
3754
3755       /* Go past the current frame. */
3756       if (cf->sbackward) {
3757         /* Go on to the previous frame. */
3758         fdata = fdata->prev;
3759         if (fdata == NULL) {
3760           /*
3761            * XXX - other apps have a bit more of a detailed message
3762            * for this, and instead of offering "OK" and "Cancel",
3763            * they offer things such as "Continue" and "Cancel";
3764            * we need an API for popping up alert boxes with
3765            * {Verb} and "Cancel".
3766            */
3767
3768           if (prefs.gui_find_wrap)
3769           {
3770               simple_status("Search reached the beginning. Continuing at end.");
3771               fdata = cf->plist_end;    /* wrap around */
3772           }
3773           else
3774           {
3775               simple_status("Search reached the beginning.");
3776               fdata = start_fd;        /* stay on previous packet */
3777           }
3778         }
3779       } else {
3780         /* Go on to the next frame. */
3781         fdata = fdata->next;
3782         if (fdata == NULL) {
3783           if (prefs.gui_find_wrap)
3784           {
3785               simple_status("Search reached the end. Continuing at beginning.");
3786               fdata = cf->plist_start;    /* wrap around */
3787           }
3788           else
3789           {
3790               simple_status("Search reached the end.");
3791               fdata = start_fd;     /* stay on previous packet */
3792           }
3793         }
3794       }
3795
3796       count++;
3797
3798       /* Is this packet in the display? */
3799       if (fdata->flags.passed_dfilter) {
3800         /* Yes.  Load its data. */
3801         if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
3802                 cf->pd, fdata->cap_len, &err, &err_info)) {
3803           /* Read error.  Report the error, and go back to the frame
3804              where we started. */
3805           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3806             cf_read_error_message(err, err_info), cf->filename);
3807           new_fd = start_fd;
3808           break;
3809         }
3810
3811     /* Does it match the search criterion? */
3812     if ((*match_function)(cf, fdata, criterion)) {
3813           new_fd = fdata;
3814           break;    /* found it! */
3815         }
3816       }
3817
3818       if (fdata == start_fd) {
3819         /* We're back to the frame we were on originally, and that frame
3820        doesn't match the search filter.  The search failed. */
3821         break;
3822       }
3823     }
3824
3825     /* We're done scanning the packets; destroy the progress bar if it
3826        was created. */
3827     if (progbar != NULL)
3828       destroy_progress_dlg(progbar);
3829   }
3830
3831   if (new_fd != NULL) {
3832 #ifdef NEW_PACKET_LIST
3833       /* Find and select */
3834       row = new_packet_list_find_row_from_data(fdata, TRUE);
3835 #else
3836     /* We found a frame.  Find what row it's in. */
3837     row = packet_list_find_row_from_data(new_fd);
3838 #endif /* NEW_PACKET_LIST */
3839     if (row == -1) {
3840         /* We didn't find a row even though we know that a frame
3841          * exists that satifies the search criteria. This means that the
3842          * frame isn't being displayed currently so we can't select it. */
3843         simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3844                       "%sEnd of capture exceeded!%s\n\n"
3845                       "The capture file is probably not fully loaded.",
3846                       simple_dialog_primary_start(), simple_dialog_primary_end());
3847         return FALSE;
3848     }
3849
3850 #ifndef NEW_PACKET_LIST
3851     /* Select that row, make it the focus row, and make it visible. */
3852     packet_list_set_selected_row(row);
3853 #endif /* NEW_PACKET_LIST */
3854     return TRUE;    /* success */
3855   } else
3856     return FALSE;   /* failure */
3857 }
3858
3859 gboolean
3860 cf_goto_frame(capture_file *cf, guint fnumber)
3861 {
3862   frame_data *fdata;
3863   int row;
3864
3865   for (fdata = cf->plist_start; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
3866     ;
3867
3868   if (fdata == NULL) {
3869     /* we didn't find a packet with that packet number */
3870     simple_status("There is no packet number %u.", fnumber);
3871     return FALSE;   /* we failed to go to that packet */
3872   }
3873   if (!fdata->flags.passed_dfilter) {
3874     /* that packet currently isn't displayed */
3875     /* XXX - add it to the set of displayed packets? */
3876     simple_status("Packet number %u isn't displayed.", fnumber);
3877     return FALSE;   /* we failed to go to that packet */
3878   }
3879
3880 #ifdef NEW_PACKET_LIST
3881   row = new_packet_list_find_row_from_data(fdata, TRUE);
3882 #else
3883   /* We found that packet, and it's currently being displayed.
3884      Find what row it's in. */
3885   row = packet_list_find_row_from_data(fdata);
3886   g_assert(row != -1);
3887
3888   /* Select that row, make it the focus row, and make it visible. */
3889   packet_list_set_selected_row(row);
3890 #endif /* NEW_PACKET_LIST */
3891   return TRUE;  /* we got to that packet */
3892 }
3893
3894 gboolean
3895 cf_goto_top_frame(capture_file *cf _U_)
3896 {
3897 #ifdef NEW_PACKET_LIST
3898   /* Find and select */
3899   new_packet_list_select_first_row();
3900 #else
3901   frame_data *fdata;
3902   int row;
3903   frame_data *lowest_fdata = NULL;
3904
3905   for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
3906     if (fdata->flags.passed_dfilter) {
3907         lowest_fdata = fdata;
3908         break;
3909     }
3910   }
3911
3912   if (lowest_fdata == NULL) {
3913       return FALSE;
3914   }
3915
3916   /* We found that packet, and it's currently being displayed.
3917      Find what row it's in. */
3918   row = packet_list_find_row_from_data(lowest_fdata);
3919   g_assert(row != -1);
3920
3921   /* Select that row, make it the focus row, and make it visible. */
3922   packet_list_set_selected_row(row);
3923 #endif /* NEW_PACKET_LIST */
3924   return TRUE;  /* we got to that packet */
3925 }
3926
3927 gboolean
3928 cf_goto_bottom_frame(capture_file *cf _U_) /* cf is unused w/ NEW_PACKET_LIST */
3929 {
3930 #ifdef NEW_PACKET_LIST
3931   /* Find and select */
3932   new_packet_list_select_last_row();
3933 #else
3934   frame_data *fdata;
3935   int row;
3936   frame_data *highest_fdata = NULL;
3937
3938   for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
3939     if (fdata->flags.passed_dfilter) {
3940         highest_fdata = fdata;
3941     }
3942   }
3943
3944   if (highest_fdata == NULL) {
3945       return FALSE;
3946   }
3947
3948   /* We found that packet, and it's currently being displayed.
3949      Find what row it's in. */
3950   row = packet_list_find_row_from_data(highest_fdata);
3951   g_assert(row != -1);
3952
3953   /* Select that row, make it the focus row, and make it visible. */
3954   packet_list_set_selected_row(row);
3955 #endif /* NEW_PACKET_LIST */
3956   return TRUE;  /* we got to that packet */
3957 }
3958
3959 /*
3960  * Go to frame specified by currently selected protocol tree item.
3961  */
3962 gboolean
3963 cf_goto_framenum(capture_file *cf)
3964 {
3965   header_field_info       *hfinfo;
3966   guint32                 framenum;
3967
3968   if (cf->finfo_selected) {
3969     hfinfo = cf->finfo_selected->hfinfo;
3970     g_assert(hfinfo);
3971     if (hfinfo->type == FT_FRAMENUM) {
3972       framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3973       if (framenum != 0)
3974         return cf_goto_frame(cf, framenum);
3975       }
3976   }
3977
3978   return FALSE;
3979 }
3980
3981 /* Select the packet on a given row. */
3982 void
3983 cf_select_packet(capture_file *cf, int row)
3984 {
3985   frame_data *fdata;
3986   int err;
3987   gchar *err_info;
3988
3989   /* Get the frame data struct pointer for this frame */
3990 #ifdef NEW_PACKET_LIST
3991   fdata = new_packet_list_get_row_data(row);
3992 #else
3993   fdata = (frame_data *)packet_list_get_row_data(row);
3994 #endif
3995
3996   if (fdata == NULL) {
3997     /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3998        the first entry is added to it by "real_insert_row()", that row
3999        is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
4000        our version and the vanilla GTK+ version).
4001
4002        This means that a "select-row" signal is emitted; this causes
4003        "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
4004        to be called.
4005
4006        "cf_select_packet()" fetches, above, the data associated with the
4007        row that was selected; however, as "gtk_clist_append()", which
4008        called "real_insert_row()", hasn't yet returned, we haven't yet
4009        associated any data with that row, so we get back a null pointer.
4010
4011        We can't assume that there's only one frame in the frame list,
4012        either, as we may be filtering the display.
4013
4014        We therefore assume that, if "row" is 0, i.e. the first row
4015        is being selected, and "cf->first_displayed" equals
4016        "cf->last_displayed", i.e. there's only one frame being
4017        displayed, that frame is the frame we want.
4018
4019        This means we have to set "cf->first_displayed" and
4020        "cf->last_displayed" before adding the row to the
4021        GtkCList; see the comment in "add_packet_to_packet_list()". */
4022
4023        if (row == 0 && cf->first_displayed == cf->last_displayed)
4024          fdata = cf->first_displayed;
4025   }
4026
4027   /* If fdata _still_ isn't set simply give up. */
4028   if (fdata == NULL) {
4029     return;
4030   }
4031
4032   /* Get the data in that frame. */
4033   if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
4034                cf->pd, fdata->cap_len, &err, &err_info)) {
4035     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4036           cf_read_error_message(err, err_info), cf->filename);
4037     return;
4038   }
4039
4040   /* Record that this frame is the current frame. */
4041   cf->current_frame = fdata;
4042   cf->current_row = row;
4043
4044   /* Create the logical protocol tree. */
4045   if (cf->edt != NULL)
4046     epan_dissect_free(cf->edt);
4047
4048   /* We don't need the columns here. */
4049   cf->edt = epan_dissect_new(TRUE, TRUE);
4050
4051   tap_build_interesting(cf->edt);
4052   epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
4053           NULL);
4054
4055   dfilter_macro_build_ftv_cache(cf->edt->tree);
4056
4057   cf_callback_invoke(cf_cb_packet_selected, cf);
4058 }
4059
4060 /* Unselect the selected packet, if any. */
4061 void
4062 cf_unselect_packet(capture_file *cf)
4063 {
4064   /* Destroy the epan_dissect_t for the unselected packet. */
4065   if (cf->edt != NULL) {
4066     epan_dissect_free(cf->edt);
4067     cf->edt = NULL;
4068   }
4069
4070   /* No packet is selected. */
4071   cf->current_frame = NULL;
4072   cf->current_row = 0;
4073
4074   cf_callback_invoke(cf_cb_packet_unselected, cf);
4075
4076   /* No protocol tree means no selected field. */
4077   cf_unselect_field(cf);
4078 }
4079
4080 /* Unset the selected protocol tree field, if any. */
4081 void
4082 cf_unselect_field(capture_file *cf)
4083 {
4084   cf->finfo_selected = NULL;
4085
4086   cf_callback_invoke(cf_cb_field_unselected, cf);
4087 }
4088
4089 /*
4090  * Mark a particular frame.
4091  */
4092 void
4093 cf_mark_frame(capture_file *cf, frame_data *frame)
4094 {
4095   if (! frame->flags.marked) {
4096     frame->flags.marked = TRUE;
4097     if (cf->count > cf->marked_count)
4098       cf->marked_count++;
4099   }
4100 }
4101
4102 /*
4103  * Unmark a particular frame.
4104  */
4105 void
4106 cf_unmark_frame(capture_file *cf, frame_data *frame)
4107 {
4108   if (frame->flags.marked) {
4109     frame->flags.marked = FALSE;
4110     if (cf->marked_count > 0)
4111       cf->marked_count--;
4112   }
4113 }
4114
4115 /*
4116  * Ignore a particular frame.
4117  */
4118 void
4119 cf_ignore_frame(capture_file *cf, frame_data *frame)
4120 {
4121   if (! frame->flags.ignored) {
4122     frame->flags.ignored = TRUE;
4123     if (cf->count > cf->ignored_count)
4124       cf->ignored_count++;
4125   }
4126 }
4127
4128 /*
4129  * Un-ignore a particular frame.
4130  */
4131 void
4132 cf_unignore_frame(capture_file *cf, frame_data *frame)
4133 {
4134   if (frame->flags.ignored) {
4135     frame->flags.ignored = FALSE;
4136     if (cf->ignored_count > 0)
4137       cf->ignored_count--;
4138   }
4139 }
4140
4141 typedef struct {
4142   wtap_dumper *pdh;
4143   const char  *fname;
4144 } save_callback_args_t;
4145
4146 /*
4147  * Save a capture to a file, in a particular format, saving either
4148  * all packets, all currently-displayed packets, or all marked packets.
4149  *
4150  * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4151  * up a message box for the failure.
4152  */
4153 static gboolean
4154 save_packet(capture_file *cf _U_, frame_data *fdata,
4155             union wtap_pseudo_header *pseudo_header, const guint8 *pd,
4156             void *argsp)
4157 {
4158   save_callback_args_t *args = argsp;
4159   struct wtap_pkthdr hdr;
4160   int           err;
4161
4162   /* init the wtap header for saving */
4163   hdr.ts.secs    = fdata->abs_ts.secs;
4164   hdr.ts.nsecs   = fdata->abs_ts.nsecs;
4165   hdr.caplen     = fdata->cap_len;
4166   hdr.len        = fdata->pkt_len;
4167   hdr.pkt_encap  = fdata->lnk_t;
4168
4169   /* and save the packet */
4170   if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
4171     cf_write_failure_alert_box(args->fname, err);
4172     return FALSE;
4173   }
4174   return TRUE;
4175 }
4176
4177 /*
4178  * Can this capture file be saved in any format except by copying the raw data?
4179  */
4180 gboolean
4181 cf_can_save_as(capture_file *cf)
4182 {
4183   int ft;
4184
4185   for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
4186     /* To save a file with Wiretap, Wiretap has to handle that format,
4187        and its code to handle that format must be able to write a file
4188        with this file's encapsulation type. */
4189     if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
4190       /* OK, we can write it out in this type. */
4191       return TRUE;
4192     }
4193   }
4194
4195   /* No, we couldn't save it in any format. */
4196   return FALSE;
4197 }
4198
4199 cf_status_t
4200 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
4201 {
4202   gchar        *from_filename;
4203   int           err;
4204   gboolean      do_copy;
4205   wtap_dumper  *pdh;
4206   save_callback_args_t callback_args;
4207
4208   cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4209
4210   /* don't write over an existing file. */
4211   /* this should've been already checked by our caller, just to be sure... */
4212   if (file_exists(fname)) {
4213     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4214       "%sCapture file: \"%s\" already exists!%s\n\n"
4215       "Please choose a different filename.",
4216       simple_dialog_primary_start(), fname, simple_dialog_primary_end());
4217     goto fail;
4218   }
4219
4220   packet_range_process_init(range);
4221
4222   if (packet_range_process_all(range) && save_format == cf->cd_t) {
4223     /* We're not filtering packets, and we're saving it in the format
4224        it's already in, so we can just move or copy the raw data. */
4225
4226     if (cf->is_tempfile) {
4227       /* The file being saved is a temporary file from a live
4228          capture, so it doesn't need to stay around under that name;
4229      first, try renaming the capture buffer file to the new name. */
4230 #ifndef _WIN32
4231       if (ws_rename(cf->filename, fname) == 0) {
4232         /* That succeeded - there's no need to copy the source file. */
4233         from_filename = NULL;
4234     do_copy = FALSE;
4235       } else {
4236         if (errno == EXDEV) {
4237       /* They're on different file systems, so we have to copy the
4238          file. */
4239       do_copy = TRUE;
4240           from_filename = cf->filename;
4241     } else {
4242       /* The rename failed, but not because they're on different
4243          file systems - put up an error message.  (Or should we
4244          just punt and try to copy?  The only reason why I'd
4245          expect the rename to fail and the copy to succeed would
4246          be if we didn't have permission to remove the file from
4247          the temporary directory, and that might be fixable - but
4248          is it worth requiring the user to go off and fix it?) */
4249       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4250                 file_rename_error_message(errno), fname);
4251       goto fail;
4252     }
4253       }
4254 #else
4255       do_copy = TRUE;
4256       from_filename = cf->filename;
4257 #endif
4258     } else {
4259       /* It's a permanent file, so we should copy it, and not remove the
4260          original. */
4261       do_copy = TRUE;
4262       from_filename = cf->filename;
4263     }
4264
4265     if (do_copy) {
4266       /* Copy the file, if we haven't moved it. */
4267       if (!copy_file_binary_mode(from_filename, fname))
4268     goto fail;
4269     }
4270   } else {
4271     /* Either we're filtering packets, or we're saving in a different
4272        format; we can't do that by copying or moving the capture file,
4273        we have to do it by writing the packets out in Wiretap. */
4274     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
4275         compressed, &err);
4276     if (pdh == NULL) {
4277       cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4278       goto fail;
4279     }
4280
4281     /* XXX - we let the user save a subset of the packets.
4282
4283        If we do that, should we make that file the current file?  If so,
4284        it means we can no longer get at the other packets.  What does
4285        NetMon do? */
4286
4287     /* Iterate through the list of packets, processing the packets we were
4288        told to process.
4289
4290        XXX - we've already called "packet_range_process_init(range)", but
4291        "process_specified_packets()" will do it again.  Fortunately,
4292        that's harmless in this case, as we haven't done anything to
4293        "range" since we initialized it. */
4294     callback_args.pdh = pdh;
4295     callback_args.fname = fname;
4296     switch (process_specified_packets(cf, range, "Saving", "selected packets",
4297                                       TRUE, save_packet, &callback_args)) {
4298
4299     case PSP_FINISHED:
4300       /* Completed successfully. */
4301       break;
4302
4303     case PSP_STOPPED:
4304       /* The user decided to abort the saving.
4305          XXX - remove the output file? */
4306       break;
4307
4308     case PSP_FAILED:
4309       /* Error while saving. */
4310       wtap_dump_close(pdh, &err);
4311       goto fail;
4312     }
4313
4314     if (!wtap_dump_close(pdh, &err)) {
4315       cf_close_failure_alert_box(fname, err);
4316       goto fail;
4317     }
4318   }
4319
4320   cf_callback_invoke(cf_cb_file_save_finished, NULL);
4321
4322   if (packet_range_process_all(range)) {
4323     /* We saved the entire capture, not just some packets from it.
4324        Open and read the file we saved it to.
4325
4326        XXX - this is somewhat of a waste; we already have the
4327        packets, all this gets us is updated file type information
4328        (which we could just stuff into "cf"), and having the new
4329        file be the one we have opened and from which we're reading
4330        the data, and it means we have to spend time opening and
4331        reading the file, which could be a significant amount of
4332        time if the file is large. */
4333     cf->user_saved = TRUE;
4334
4335     if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
4336       /* XXX - report errors if this fails?
4337          What should we return if it fails or is aborted? */
4338
4339       switch (cf_read(cf, TRUE)) {
4340
4341       case CF_READ_OK:
4342       case CF_READ_ERROR:
4343     /* Just because we got an error, that doesn't mean we were unable
4344        to read any of the file; we handle what we could get from the
4345        file. */
4346     break;
4347
4348       case CF_READ_ABORTED:
4349     /* The user bailed out of re-reading the capture file; the
4350        capture file has been closed - just return (without
4351        changing any menu settings; "cf_close()" set them
4352        correctly for the "no capture file open" state). */
4353     break;
4354       }
4355       cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
4356     }
4357   }
4358   return CF_OK;
4359
4360 fail:
4361   cf_callback_invoke(cf_cb_file_save_failed, NULL);
4362   return CF_ERROR;
4363 }
4364
4365 static void
4366 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4367                           gboolean for_writing, int file_type)
4368 {
4369   if (err < 0) {
4370     /* Wiretap error. */
4371     switch (err) {
4372
4373     case WTAP_ERR_NOT_REGULAR_FILE:
4374       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4375             "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4376             filename);
4377       break;
4378
4379     case WTAP_ERR_RANDOM_OPEN_PIPE:
4380       /* Seen only when opening a capture file for reading. */
4381       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4382             "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
4383             filename);
4384       break;
4385
4386     case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4387       /* Seen only when opening a capture file for reading. */
4388       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4389             "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4390             filename);
4391       break;
4392
4393     case WTAP_ERR_UNSUPPORTED:
4394       /* Seen only when opening a capture file for reading. */
4395       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4396             "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
4397             "(%s)",
4398             filename, err_info);
4399       g_free(err_info);
4400       break;
4401
4402     case WTAP_ERR_CANT_WRITE_TO_PIPE:
4403       /* Seen only when opening a capture file for writing. */
4404       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4405             "The file \"%s\" is a pipe, and %s capture files can't be "
4406             "written to a pipe.",
4407             filename, wtap_file_type_string(file_type));
4408       break;
4409
4410     case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
4411       /* Seen only when opening a capture file for writing. */
4412       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4413             "Wireshark doesn't support writing capture files in that format.");
4414       break;
4415
4416     case WTAP_ERR_UNSUPPORTED_ENCAP:
4417       if (for_writing) {
4418     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4419               "Wireshark can't save this capture in that format.");
4420       } else {
4421     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4422               "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
4423               "(%s)",
4424               filename, err_info);
4425         g_free(err_info);
4426       }
4427       break;
4428
4429     case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4430       if (for_writing) {
4431     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4432               "Wireshark can't save this capture in that format.");
4433       } else {
4434     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4435               "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4436               filename);
4437       }
4438       break;
4439
4440     case WTAP_ERR_BAD_RECORD:
4441       /* Seen only when opening a capture file for reading. */
4442       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4443             "The file \"%s\" appears to be damaged or corrupt.\n"
4444             "(%s)",
4445             filename, err_info);
4446       g_free(err_info);
4447       break;
4448
4449     case WTAP_ERR_CANT_OPEN:
4450       if (for_writing) {
4451     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4452               "The file \"%s\" could not be created for some unknown reason.",
4453               filename);
4454       } else {
4455     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4456               "The file \"%s\" could not be opened for some unknown reason.",
4457               filename);
4458       }
4459       break;
4460
4461     case WTAP_ERR_SHORT_READ:
4462       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4463             "The file \"%s\" appears to have been cut short"
4464             " in the middle of a packet or other data.",
4465             filename);
4466       break;
4467
4468     case WTAP_ERR_SHORT_WRITE:
4469       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4470             "A full header couldn't be written to the file \"%s\".",
4471             filename);
4472       break;
4473
4474     case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4475       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4476             "Gzip compression not supported by this file type.");
4477       break;
4478
4479     default:
4480       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4481             "The file \"%s\" could not be %s: %s.",
4482             filename,
4483             for_writing ? "created" : "opened",
4484             wtap_strerror(err));
4485       break;
4486     }
4487   } else {
4488     /* OS error. */
4489     open_failure_alert_box(filename, err, for_writing);
4490   }
4491 }
4492
4493 static const char *
4494 file_rename_error_message(int err)
4495 {
4496   const char *errmsg;
4497   static char errmsg_errno[1024+1];
4498
4499   switch (err) {
4500
4501   case ENOENT:
4502     errmsg = "The path to the file \"%s\" doesn't exist.";
4503     break;
4504
4505   case EACCES:
4506     errmsg = "You don't have permission to move the capture file to \"%s\".";
4507     break;
4508
4509   default:
4510     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4511             "The file \"%%s\" could not be moved: %s.",
4512                 wtap_strerror(err));
4513     errmsg = errmsg_errno;
4514     break;
4515   }
4516   return errmsg;
4517 }
4518
4519 char *
4520 cf_read_error_message(int err, gchar *err_info)
4521 {
4522   static char errmsg_errno[1024+1];
4523
4524   switch (err) {
4525
4526   case WTAP_ERR_UNSUPPORTED_ENCAP:
4527     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4528                "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
4529                err_info);
4530     g_free(err_info);
4531     break;
4532
4533   case WTAP_ERR_BAD_RECORD:
4534     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4535          "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
4536          wtap_strerror(err), err_info);
4537     g_free(err_info);
4538     break;
4539
4540   default:
4541     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
4542          "An error occurred while reading from the file \"%%s\": %s.",
4543          wtap_strerror(err));
4544     break;
4545   }
4546   return errmsg_errno;
4547 }
4548
4549 static void
4550 cf_write_failure_alert_box(const char *filename, int err)
4551 {
4552   if (err < 0) {
4553     /* Wiretap error. */
4554     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4555           "An error occurred while writing to the file \"%s\": %s.",
4556           filename, wtap_strerror(err));
4557   } else {
4558     /* OS error. */
4559     write_failure_alert_box(filename, err);
4560   }
4561 }
4562
4563 /* Check for write errors - if the file is being written to an NFS server,
4564    a write error may not show up until the file is closed, as NFS clients
4565    might not send writes to the server until the "write()" call finishes,
4566    so that the write may fail on the server but the "write()" may succeed. */
4567 static void
4568 cf_close_failure_alert_box(const char *filename, int err)
4569 {
4570   if (err < 0) {
4571     /* Wiretap error. */
4572     switch (err) {
4573
4574     case WTAP_ERR_CANT_CLOSE:
4575       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4576             "The file \"%s\" couldn't be closed for some unknown reason.",
4577             filename);
4578       break;
4579
4580     case WTAP_ERR_SHORT_WRITE:
4581       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4582             "Not all the packets could be written to the file \"%s\".",
4583                     filename);
4584       break;
4585
4586     default:
4587       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
4588             "An error occurred while closing the file \"%s\": %s.",
4589             filename, wtap_strerror(err));
4590       break;
4591     }
4592   } else {
4593     /* OS error.
4594        We assume that a close error from the OS is really a write error. */
4595     write_failure_alert_box(filename, err);
4596   }
4597 }
4598
4599 /* Reload the current capture file. */
4600 void
4601 cf_reload(capture_file *cf) {
4602   gchar *filename;
4603   gboolean is_tempfile;
4604   int err;
4605
4606   /* If the file could be opened, "cf_open()" calls "cf_close()"
4607      to get rid of state for the old capture file before filling in state
4608      for the new capture file.  "cf_close()" will remove the file if
4609      it's a temporary file; we don't want that to happen (for one thing,
4610      it'd prevent subsequent reopens from working).  Remember whether it's
4611      a temporary file, mark it as not being a temporary file, and then
4612      reopen it as the type of file it was.
4613
4614      Also, "cf_close()" will free "cf->filename", so we must make
4615      a copy of it first. */
4616   filename = g_strdup(cf->filename);
4617   is_tempfile = cf->is_tempfile;
4618   cf->is_tempfile = FALSE;
4619   if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
4620     switch (cf_read(cf, FALSE)) {
4621
4622     case CF_READ_OK:
4623     case CF_READ_ERROR:
4624       /* Just because we got an error, that doesn't mean we were unable
4625          to read any of the file; we handle what we could get from the
4626          file. */
4627       break;
4628
4629     case CF_READ_ABORTED:
4630       /* The user bailed out of re-reading the capture file; the
4631          capture file has been closed - just free the capture file name
4632          string and return (without changing the last containing
4633          directory). */
4634       g_free(filename);
4635       return;
4636     }
4637   } else {
4638     /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4639        Instead, the file was left open, so we should restore "cf->is_tempfile"
4640        ourselves.
4641
4642        XXX - change the menu?  Presumably "cf_open()" will do that;
4643        make sure it does! */
4644     cf->is_tempfile = is_tempfile;
4645   }
4646   /* "cf_open()" made a copy of the file name we handed it, so
4647      we should free up our copy. */
4648   g_free(filename);
4649 }
4650
4651 /*
4652  * Editor modelines
4653  *
4654  * Local Variables:
4655  * c-basic-offset: 2
4656  * tab-width: 8
4657  * indent-tabs-mode: nil
4658  * End:
4659  *
4660  * ex: set shiftwidth=2 tabstop=8 expandtab
4661  * :indentSize=2:tabSize=8:noTabs=true:
4662  */