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