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