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