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