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