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