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