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