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