Remove the fixed maximum number of subranges in a range_t; dynamically
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 16 Oct 2004 23:32:24 +0000 (23:32 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 16 Oct 2004 23:32:24 +0000 (23:32 +0000)
allocate them to be large enough.

Add checks that the numbers in the range fit in a guint32.

Check the validity of a range before saving or printing, and report
errors in an alert box.

Clean up white space.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@12320 f5534014-38df-0310-8fa8-9805f1628bb7

13 files changed:
epan/dissectors/packet-tcap.c
epan/prefs-int.h
epan/prefs.c
epan/prefs.h
epan/range.c
epan/range.h
gtk/file_dlg.c
gtk/prefs_dlg.c
gtk/print_dlg.c
gtk/range_utils.c
gtk/range_utils.h
packet-range.c
packet-range.h

index d00dcc0084ad966e871205d5a1b924638ebcc58f..1938a38ce31915e055ef15c3f7d4c384b2ff27b6 100644 (file)
@@ -67,8 +67,8 @@
 Tcap_Standard_Type tcap_standard = ITU_TCAP_STANDARD;
 
 #define MAX_SSN 254
-static range_t global_ssn_range;
-static range_t ssn_range;
+static range_t *global_ssn_range;
+static range_t *ssn_range;
 
 static dissector_handle_t tcap_handle;
 
@@ -2866,7 +2866,7 @@ proto_register_tcap(void)
 
     /* Set default SSNs */
     range_convert_str(&global_ssn_range, "5-12", MAX_SSN);
-    memset(&ssn_range, 0, sizeof(ssn_range));
+    ssn_range = range_empty();
 
     prefs_register_range_preference(tcap_module, "ssn", "SCCP SSNs",
        "SCCP (and SUA) SSNs to decode as TCAP",
@@ -2913,11 +2913,12 @@ proto_reg_handoff_tcap(void)
 
     } else {
 
-       range_foreach(&ssn_range, range_delete_callback);
+       range_foreach(ssn_range, range_delete_callback);
     }
 
+    g_free(ssn_range);
     ssn_range = global_ssn_range;
 
-    range_foreach(&ssn_range, range_add_callback);
+    range_foreach(ssn_range, range_add_callback);
 
 }
index e3b5617301fc3da291beb0b054c0c4b99f5d967d..cbcec1d52a44f908d4d402e9247df3298161db80 100644 (file)
@@ -68,14 +68,14 @@ struct preference {
                gboolean *boolp;
                gint *enump;
                char **string;
-               range_t *rangep;
+               range_t **range;
        } varp;                 /* pointer to variable storing the value */
        union {
                guint uint;
                gboolean boolval;
                gint enumval;
                char *string;
-               range_t rangeval;
+               range_t *range;
        } saved_val;            /* original value, when editing from the GUI */
        union {
          guint base;                   /* input/output base, for PREF_UINT */
index a44252d47cc28ecc7667f92ae47ce0324a4346ff..38eca978e64fce577486860e7b3b047bb5eda3ad 100644 (file)
@@ -566,7 +566,7 @@ prefs_register_string_preference(module_t *module, const char *name,
         * String preference values should be non-null (as you can't
         * keep them null after using the preferences GUI, you can at best
         * have them be null strings) and freeable (as we free them
-        * if we change them.
+        * if we change them).
         *
         * If the value is a null pointer, make it a copy of a null
         * string, otherwise make it a copy of the value.
@@ -584,7 +584,7 @@ prefs_register_string_preference(module_t *module, const char *name,
  */
 void
 prefs_register_range_preference(module_t *module, const char *name,
-    const char *title, const char *description, range_t *var,
+    const char *title, const char *description, range_t **var,
     guint32 max_value)
 {
        pref_t *preference;
@@ -593,8 +593,22 @@ prefs_register_range_preference(module_t *module, const char *name,
                                         PREF_RANGE);
        preference->info.max_value = max_value;
 
-       preference->varp.rangep = var;
-       memset(&preference->saved_val.rangeval, 0, sizeof(preference->saved_val.rangeval));
+
+       /*
+        * Range preference values should be non-null (as you can't
+        * keep them null after using the preferences GUI, you can at best
+        * have them be empty ranges) and freeable (as we free them
+        * if we change them).
+        *
+        * If the value is a null pointer, make it an empty range,
+        * otherwise make it a copy of the value.
+        */
+       if (*var == NULL)
+               *var = range_empty();
+       else
+               *var = range_copy(*var);
+       preference->varp.range = var;
+       preference->saved_val.range = NULL;
 }
 
 /*
@@ -2020,18 +2034,19 @@ set_pref(gchar *pref_name, gchar *value)
 
     case PREF_RANGE:
     {
-      range_t newrange;
+      range_t *newrange;
 
       if (range_convert_str(&newrange, value, pref->info.max_value) !=
           CVT_NO_ERROR) {
         /* XXX - distinguish between CVT_SYNTAX_ERROR and
-           CVT_TOO_MANY_SUBRANGES */
+           CVT_NUMBER_TOO_BIG */
         return PREFS_SET_SYNTAX_ERR;   /* number was bad */
       }
 
-      if (!ranges_are_equal(pref->varp.rangep, &newrange)) {
+      if (!ranges_are_equal(*pref->varp.range, newrange)) {
        module->prefs_changed = TRUE;
-       *pref->varp.rangep = newrange;
+       g_free(*pref->varp.range);
+       *pref->varp.range = newrange;
       }
       break;
     }
@@ -2141,7 +2156,7 @@ write_pref(gpointer data, gpointer user_data)
 
                fprintf(arg->pf, "# A string denoting an positive integer range (e.g., \"1-20,30-40\").\n");
                fprintf(arg->pf, "%s.%s: %s\n", arg->module->name, pref->name,
-                       range_convert_range(pref->varp.rangep, range_string));
+                       range_convert_range(*pref->varp.range, range_string));
                break;
        }
 
index f4cb4e023ff19e00195f1d869a7cbd64f904da2b..b77539c849a6a1f23ec7750ca57a2d3462cff171 100644 (file)
@@ -280,7 +280,7 @@ extern void prefs_register_string_preference(module_t *module, const char *name,
  * Register a preference with a ranged value.
  */
 extern void prefs_register_range_preference(module_t *module, const char *name,
-    const char *title, const char *description, range_t *var,
+    const char *title, const char *description, range_t **var,
     guint32 max_value);
 
 /*
index dcfef8b548bc4d49274c662ff5cff6a2d4d4561d..adf159123904c4699daa71de00f4c948919633ed 100644 (file)
 #include <epan/range.h>
 #include <stdio.h>
 
-/* init the range struct */
-void range_init(range_t *range) {
+/*
+ * GLib 1.2[.x] doesn't define G_MAXUINT32; if it's not defined, we define
+ * it as the maximum 32-bit unsigned number.
+ */
+#ifndef G_MAXUINT32
+#define G_MAXUINT32    ((guint32)0xFFFFFFFFU)
+#endif
+
+/*
+ * Size of the header of a range_t.
+ */
+#define RANGE_HDR_SIZE (sizeof (range_t) - sizeof (range_admin_t))
 
-  range->nranges            = 0;
-  range->ranges[range->nranges].low  = 0L;
-  range->ranges[range->nranges].high = 0L;
+/* Allocate an empty range. */
+range_t *range_empty(void)
+{
+   range_t *range;
+
+   range = g_malloc(RANGE_HDR_SIZE);
+   range->nranges = 0;
+   return range;
 }
 
 /******************** Range Entry Parser *********************************/
@@ -54,10 +69,11 @@ void range_init(range_t *range) {
  * The parameter 'max_value' specifies the maximum value in a
  * range.
  *
- * This function fills the array range->ranges containing low and high values
- * with the number of ranges being range->nranges. After having called this
- * function, the function value_is_in_range() determines whether a given
- * number is within the range or not. 
+ * This function allocates a range_t large enough to hold the number
+ * of ranges specified, and fills the array range->ranges containing
+ * low and high values with the number of ranges being range->nranges.
+ * After having called this function, the function value_is_in_range()
+ * determines whether a given number is within the range or not. 
  *
  * In case of a single number, we make a range where low is equal to high. 
  * We take care on wrongly entered ranges; opposite order will be taken
@@ -72,127 +88,158 @@ void range_init(range_t *range) {
  *   -              All values
  */
 
-convert_ret_t
-range_convert_str(range_t *range, const gchar *es, guint32 max_value)
+convert_ret_t range_convert_str(range_t **rangep, const gchar *es,
+                               guint32 max_value)
 {
-    const gchar   *p;
-    char          *endp;
-    gchar         c;
-    guint         i;
-    guint32       tmp;
-    unsigned long val;
-
-    /* Reset the number of ranges we are going to find */
-    range->nranges = 0;
-    range->ranges[range->nranges].low  = 0L;
-    range->ranges[range->nranges].high = 0L;
-
-    /* Process the ranges separately until we get a comma or end of string.
-     *
-     * We build a structure array called ranges of high and low values. After the
-     * following loop, we have the nranges variable which tells how many ranges
-     * were found. The number of individual ranges is limited to 'MaxRanges'
-     */
-
-    p = es;
-    for (;;) {
-       /* Skip white space. */
-       while ((c = *p) == ' ' || c == '\t')
-                  p++;
-       if (c == '\0')
-           break;
-
-       /* This must be a subrange. */
-       if (range->nranges == MaxRange) {
-                  /* We've filled up the structure; no room for any more. */
-           return CVT_TOO_MANY_SUBRANGES;
-       }
-
-       if (c == '-') {
-           /* Subrange starts with 1. */
-           range->ranges[range->nranges].low = 1;
-       } else {
-           /* Subrange starts with the specified number */
-           val = strtol(p, &endp, 10);
-           if (p == endp) {
-               /* That wasn't a valid number. */
-               return CVT_SYNTAX_ERROR;
-           }
-           p = endp;
-           range->ranges[range->nranges].low = val;
-
-           /* Skip white space. */
-           while ((c = *p) == ' ' || c == '\t')
-               p++;
-       }
-
-       if (c == '-') {
-           /* There's a hyphen in the range.  Skip past it. */
-           p++;
-
-           /* Skip white space. */
-           while ((c = *p) == ' ' || c == '\t')
-               p++;
-
-           if (c == ',' || c == '\0') {
-               /*
-                * End of subrange string; that means the subrange ends
-                * with max_value.
-                */
-               range->ranges[range->nranges].high = max_value;
-           } else {
-               /* Subrange ends with the specified number. */
-               val = strtol(p, &endp, 10);
-               if (p == endp) {
-                   /* That wasn't a valid number. */
-                   return CVT_SYNTAX_ERROR;
-               }
-               p = endp;
-               range->ranges[range->nranges].high = val;
-
-               /* Skip white space. */
-               while ((c = *p) == ' ' || c == '\t')
-                   p++;
-           }
-       } else if (c == ',' || c == '\0') {
-           /*
-            * End of subrange string; that means there's no hyphen
-            * in the subrange, so the start and the end are the same.
-            */
-           range->ranges[range->nranges].high =
-               range->ranges[range->nranges].low;
-       } else {
-          /* Invalid character. */ 
-          return CVT_SYNTAX_ERROR;
-       }
-       range->nranges++;
-
-       if (c == ',') {
-                  /* Subrange is followed by a comma; skip it. */
-           p++;
-       }
-    }
-
-    /*  Now we are going through the low and high values, and check
-     *  whether they are in a proper order. Low should be equal or lower
-     *  than high. So, go through the loop and swap if needed.
-     */
-    for (i=0; i < range->nranges; i++) {
-       if (range->ranges[i].low > range->ranges[i].high) {
-          tmp = range->ranges[i].low;
-          range->ranges[i].low  = range->ranges[i].high;
-          range->ranges[i].high = tmp;
-       }
-    }
-
-    /* In case we want to know what the result ranges are :
-     *
-     * for (i=0; i < range->nranges; i++) {
-     *  printf("Function : range_convert_str L=%u \t H=%u\n",range->ranges[i].low,range->ranges[i].high);
-     * }
-     *
-     */
-     return CVT_NO_ERROR;
+   range_t       *range;
+   guint         nranges;
+   const gchar   *p;
+   char          *endp;
+   gchar         c;
+   guint         i;
+   guint32       tmp;
+   unsigned long val;
+
+   /* Allocate a range; this has room for one subrange. */
+   range = g_malloc(RANGE_HDR_SIZE + sizeof (range_admin_t));
+   range->nranges = 0;
+   nranges = 1;
+
+   /* Process the ranges separately until we get a comma or end of string.
+    *
+    * We build a structure array called ranges of high and low values. After the
+    * following loop, we have the nranges variable which tells how many ranges
+    * were found. The number of individual ranges is limited to 'MaxRanges'
+    */
+
+   p = es;
+   for (;;) {
+      /* Skip white space. */
+      while ((c = *p) == ' ' || c == '\t')
+        p++;
+      if (c == '\0')
+        break;
+
+      /* This must be a subrange.  Make sure we have room for it. */
+      if (range->nranges >= nranges) {
+        /* Grow the structure.
+         * 4 is an arbitrarily chosen number.
+         * We start with 1, under the assumption that people
+         * will often give a single number or range, and then
+         * proceed to keep it a multiple of 4.
+         */
+        if (nranges == 1)
+           nranges = 4;
+        else
+           nranges += 4;
+        range = g_realloc(range, RANGE_HDR_SIZE +
+                          nranges*sizeof (range_admin_t));
+      }
+
+      if (c == '-') {
+        /* Subrange starts with 1. */
+        range->ranges[range->nranges].low = 1;
+      } else if (isdigit((unsigned char)c)) {
+        /* Subrange starts with the specified number */
+        val = strtol(p, &endp, 10);
+        if (p == endp) {
+           /* That wasn't a valid number. */
+           g_free(range);
+           return CVT_SYNTAX_ERROR;
+        }
+        if (val > G_MAXUINT32) {
+           /* That was valid, but it's too big. */
+           g_free(range);
+           return CVT_NUMBER_TOO_BIG;
+        } 
+        p = endp;
+        range->ranges[range->nranges].low = val;
+
+        /* Skip white space. */
+        while ((c = *p) == ' ' || c == '\t')
+           p++;
+      } else {
+        /* Neither empty nor a number. */
+        g_free(range);
+        return CVT_SYNTAX_ERROR;
+      }
+
+      if (c == '-') {
+        /* There's a hyphen in the range.  Skip past it. */
+        p++;
+
+        /* Skip white space. */
+        while ((c = *p) == ' ' || c == '\t')
+           p++;
+
+        if (c == ',' || c == '\0') {
+          /* End of subrange string; that means the subrange ends
+           * with max_value.
+           */
+          range->ranges[range->nranges].high = max_value;
+        } else if (isdigit((unsigned char)c)) {
+           /* Subrange ends with the specified number. */
+          val = strtoul(p, &endp, 10);
+          if (p == endp) {
+             /* That wasn't a valid number. */
+             g_free(range);
+             return CVT_SYNTAX_ERROR;
+          }
+          if (val > G_MAXUINT32) {
+             /* That was valid, but it's too big. */
+             g_free(range);
+             return CVT_NUMBER_TOO_BIG;
+          } 
+          p = endp;
+          range->ranges[range->nranges].high = val;
+
+          /* Skip white space. */
+          while ((c = *p) == ' ' || c == '\t')
+             p++;
+        } else {
+           /* Neither empty nor a number. */
+           g_free(range);
+           return CVT_SYNTAX_ERROR;
+        }
+      } else if (c == ',' || c == '\0') {
+        /* End of subrange string; that means there's no hyphen
+         * in the subrange, so the start and the end are the same.
+         */
+        range->ranges[range->nranges].high = range->ranges[range->nranges].low;
+      } else {
+        /* Invalid character. */ 
+        g_free(range);
+        return CVT_SYNTAX_ERROR;
+      }
+      range->nranges++;
+
+      if (c == ',') {
+        /* Subrange is followed by a comma; skip it. */
+        p++;
+      }
+   }
+
+   /* Now we are going through the low and high values, and check
+    * whether they are in a proper order. Low should be equal or lower
+    * than high. So, go through the loop and swap if needed.
+    */
+   for (i=0; i < range->nranges; i++) {
+      if (range->ranges[i].low > range->ranges[i].high) {
+        tmp = range->ranges[i].low;
+        range->ranges[i].low  = range->ranges[i].high;
+        range->ranges[i].high = tmp;
+      }
+   }
+
+   /* In case we want to know what the result ranges are :
+    *
+    * for (i=0; i < range->nranges; i++) {
+    *  printf("Function : range_convert_str L=%u \t H=%u\n",range->ranges[i].low,range->ranges[i].high);
+    * }
+    *
+    */
+   *rangep = range;
+   return CVT_NO_ERROR;
 } /* range_convert_str */
 
 /* This function returns TRUE if a given value is within one of the ranges
@@ -204,7 +251,7 @@ gboolean value_is_in_range(range_t *range, guint32 val)
 
    for (i=0; i < range->nranges; i++) {
       if (val >= range->ranges[i].low && val <= range->ranges[i].high)
-         return TRUE;
+        return TRUE;
    }
    return(FALSE);
 }
@@ -240,7 +287,7 @@ range_foreach(range_t *range, void (*callback)(guint32 val))
 
    for (i=0; i < range->nranges; i++) {
       for (j = range->ranges[i].low; j <= range->ranges[i].high; j++)
-         callback(j);
+        callback(j);
    }
 }
 
@@ -265,6 +312,18 @@ range_convert_range(range_t *range, char *string)
 
 }
 
+/* Create a copy of a range. */
+range_t *range_copy(range_t *src)
+{
+   range_t *dst;
+   size_t range_size;
+
+   range_size = RANGE_HDR_SIZE + src->nranges*sizeof (range_admin_t);
+   dst = g_malloc(range_size);
+   memcpy(dst, src, range_size);
+   return dst;
+}
+
 #if 0
 /* This is a debug function to check the range functionality */
 static void value_is_in_range_check(range_t *range, guint32 val)
@@ -280,3 +339,4 @@ static void value_is_in_range_check(range_t *range, guint32 val)
   }
 }
 #endif
+
index 8f6f43f6babd24500e86386c13f07970a91ae570..de88cfb77a20d4f73d4bc0d4d4ac87c220e657ee 100644 (file)
@@ -32,9 +32,6 @@
 
 #include <epan/frame_data.h>
 
-/* Range parser variables */
-#define MaxRange  30
-
 #define MAXRANGESTRING 255
 
 typedef struct range_admin_tag {
@@ -44,8 +41,8 @@ typedef struct range_admin_tag {
 
 typedef struct range {
     /* user specified range(s) */
-    guint           nranges;        /* number of entries in ranges (0 based) */
-    range_admin_t   ranges[MaxRange];
+    guint           nranges;   /* number of entries in ranges */
+    range_admin_t   ranges[1]; /* variable-length array */
 } range_t;
 
 /*
@@ -54,12 +51,12 @@ typedef struct range {
 typedef enum {
     CVT_NO_ERROR,
     CVT_SYNTAX_ERROR,
-    CVT_TOO_MANY_SUBRANGES
+    CVT_NUMBER_TOO_BIG
 } convert_ret_t;       
 
-extern void range_init(range_t *range);
+extern range_t *range_empty(void);
 
-extern convert_ret_t range_convert_str(range_t *range, const gchar *es,
+extern convert_ret_t range_convert_str(range_t **range, const gchar *es,
     guint32 max_value);
 
 extern gboolean value_is_in_range(range_t *range, guint32 val);
@@ -70,4 +67,6 @@ extern void range_foreach(range_t *range, void (*callback)(guint32 val));
 
 extern char *range_convert_range(range_t *range, char *string);
 
+extern range_t *range_copy(range_t *src);
+
 #endif /* __RANGE_H__ */
index 565754d722102f95611b5b80fd4bd008731dcd47..535e84e9fc43f6474ff5c83586ffd0088a6d9ddc 100644 (file)
@@ -1385,6 +1385,24 @@ file_save_as_ok_cb(GtkWidget *w _U_, gpointer fs) {
         return;
   }
 
+  /* Check whether the range is valid. */
+  if (!range_check_validity(&range)) {
+    /* The range isn't valid; don't dismiss the open dialog box,
+       just leave it around so that the user can, after they
+       dismiss the alert box popped up for the error, try again. */
+    g_free(cf_name);
+#if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
+    /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
+     * as this will prevent the user from closing the now existing error
+     * message, simply close the dialog (this is the best we can do here). */
+    if (file_save_as_w)
+      window_destroy(GTK_WIDGET (fs));
+#else
+    gtk_widget_show(GTK_WIDGET (fs));
+#endif
+    return;
+  }
+
   /* don't show the dialog while saving */
   gtk_widget_hide(GTK_WIDGET (fs));
 
@@ -1396,9 +1414,9 @@ file_save_as_ok_cb(GtkWidget *w _U_, gpointer fs) {
        dismiss the alert box popped up for the error, try again. */
     g_free(cf_name);
 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
-    /* as we cannot start a new event loop (using gtk_dialog_run()), as this 
-     * will prevent the user from closing the now existing error message, 
-     * simply close the dialog (this is the best we can do here). */
+    /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
+     * as this will prevent the user from closing the now existing error
+     * message, simply close the dialog (this is the best we can do here). */
     if (file_save_as_w)
       window_destroy(GTK_WIDGET (fs));
 #else
index c5c305ed1673a1ba53d69110acf595491988d9be..f2b31f4c60e9ab75e00d89dd2a8e8146d7644dbc 100644 (file)
@@ -206,8 +206,10 @@ pref_show(pref_t *pref, gpointer user_data)
   {
     char range_string[MAXRANGESTRING];
 
-    pref->saved_val.rangeval = *pref->varp.rangep;
-    range_convert_range(pref->varp.rangep, range_string);
+    if (pref->saved_val.range != NULL)
+      g_free(pref->saved_val.range);
+    pref->saved_val.range = range_copy(*pref->varp.range);
+    range_convert_range(*pref->varp.range, range_string);
     pref->control = create_preference_entry(main_tb, pref->ordinal,
                                            label_string, pref->description,
                                            range_string);
@@ -901,14 +903,15 @@ pref_check(pref_t *pref, gpointer user_data)
   case PREF_RANGE:
     str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
 
-    if (strlen(str_val)) {
-       range_t newrange;
+    if (strlen(str_val) != 0) {
+       range_t *newrange;
 
        if (range_convert_str(&newrange, str_val, pref->info.max_value) !=
            CVT_NO_ERROR) {
            *badpref = pref;
            return PREFS_SET_SYNTAX_ERR;        /* range was bad */
        }
+       g_free(newrange);
     }
     break;
 
@@ -988,21 +991,24 @@ pref_fetch(pref_t *pref, gpointer user_data)
 
   case PREF_RANGE:
   {
-    range_t newrange;
+    range_t *newrange;
     convert_ret_t ret;
 
     str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
     ret = range_convert_str(&newrange, str_val, pref->info.max_value);
-#if 0
     if (ret != CVT_NO_ERROR)
+#if 0
       return PREFS_SET_SYNTAX_ERR;     /* range was bad */
+#else
+      return 0;        /* XXX - should fail */
 #endif
 
-    if (!ranges_are_equal(pref->varp.rangep, &newrange))
-    {
+    if (!ranges_are_equal(*pref->varp.range, newrange)) {
       *pref_changed_p = TRUE;
-      *pref->varp.rangep = newrange;
-    }
+      g_free(*pref->varp.range);
+      *pref->varp.range = newrange;
+    } else
+      g_free(newrange);
 
     break;
   }
@@ -1055,6 +1061,10 @@ pref_clean(pref_t *pref, gpointer user_data _U_)
     break;
 
   case PREF_RANGE:
+    if (pref->saved_val.range != NULL) {
+      g_free(pref->saved_val.range);
+      pref->saved_val.range = NULL;
+    }
     break;
 
   case PREF_OBSOLETE:
@@ -1314,10 +1324,10 @@ pref_revert(pref_t *pref, gpointer user_data)
     break;
 
   case PREF_RANGE:
-    if (!ranges_are_equal(pref->varp.rangep, &pref->saved_val.rangeval))
-    {
+    if (!ranges_are_equal(*pref->varp.range, pref->saved_val.range)) {
       *pref_changed_p = TRUE;
-      *pref->varp.rangep = pref->saved_val.rangeval;
+      g_free(*pref->varp.range);
+      *pref->varp.range = range_copy(pref->saved_val.range);
     }
     break;
 
index 938c236e261de5e8640f1b73bfd5360fe6563ce6..1dd30a5b3641c22913f0f2a5df68086ea0a33e3e 100644 (file)
@@ -748,6 +748,14 @@ print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
 
   args = (print_args_t *)OBJECT_GET_DATA(ok_bt, PRINT_ARGS_KEY);
 
+  /* Check whether the range is valid. */
+  if (!range_check_validity(&args->range)) {
+    /* The range isn't valid; don't dismiss the print/export dialog box,
+       just leave it around so that the user can, after they
+       dismiss the alert box popped up for the error, try again. */
+    return;
+  }
+
   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_DEST_CB_KEY);
   args->to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
 
index 824635d000e74a87f7c3f6f692e99cf7093f632c..b35894275c165e592bd54827855f552519a9fc06 100644 (file)
@@ -36,6 +36,7 @@
 #include "ui_util.h"
 #include "dlg_utils.h"
 #include "compat_macros.h"
+#include "simple_dialog.h"
 
 
 #define RANGE_VALUES_KEY                "range_values"
 #define RANGE_SELECT_USER_D_KEY         "range_select_user_range_d_lb"
 #define RANGE_SELECT_USER_ENTRY_KEY     "range_select_user_range_entry"
 
+gboolean
+range_check_validity(packet_range_t *range)
+{
+  switch (packet_range_check(range)) {
+
+  case CVT_NO_ERROR:
+    return TRUE;
+
+  case CVT_SYNTAX_ERROR:
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      "The specified range of packets isn't a valid range.");
+    return FALSE;
+
+  case CVT_NUMBER_TOO_BIG:
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      "The specified range of packets has a packet number that's too large.");
+    return FALSE;
 
+  default:
+    g_assert_not_reached();
+    return FALSE;
+  }
+}
 
 /* update all "dynamic" things */
 void
index 3bd4303f4b6f980832a0513421ff8a385e602825..fded166d463407c6afc1ca532c16d56bc95d1578 100644 (file)
  *  Packet range widget used for example in the "Save" and "Print" dialogs.
  */
 
+/** Check the validity of a packet_range_t, and put up an alert box if
+ ** it's not valid.
+ *
+ * @param range the range to check
+ * @return a Boolean that's TRUE if it's valid and FALSE if it isn't
+ */
+extern gboolean range_check_validity(packet_range_t *range);
+
 /** Create a new range widget.
  *
  * @param range the range to set
index 0171b5115a4e9d607e49742f83b82eecc1c5fc9e..b39c6fce8fa5c0ac30dc961106dd41ad05ff49a3 100644 (file)
@@ -131,7 +131,7 @@ void packet_range_calc(packet_range_t *range) {
 
 
 /* (re-)calculate the user specified packet range counts */
-void packet_range_calc_user(packet_range_t *range) {
+static void packet_range_calc_user(packet_range_t *range) {
   guint32       current_count;
   frame_data    *packet;
 
@@ -142,7 +142,7 @@ void packet_range_calc_user(packet_range_t *range) {
   for(packet = cfile.plist; packet != NULL; packet = packet->next) {
       current_count++;
 
-      if (value_is_in_range(&range->user_range, current_count)) {
+      if (value_is_in_range(range->user_range, current_count)) {
           range->user_range_cnt++;
           if (packet->flags.passed_dfilter) {
             range->displayed_user_range_cnt++;
@@ -157,15 +157,25 @@ void packet_range_init(packet_range_t *range) {
 
   range->process            = range_process_all;
   range->process_filtered   = FALSE;
-  range_init(&range->user_range);
+  range->user_range         = range_empty();
 
   /* calculate all packet range counters */
   packet_range_calc(range);
   packet_range_calc_user(range);
 }
 
+/* check whether the packet range is OK */
+convert_ret_t packet_range_check(packet_range_t *range) {
+  if (range->process == range_process_user_range && range->user_range == NULL) {
+    /* Not valid - return the error. */
+    return range->user_range_status;
+  }
+  return CVT_NO_ERROR;
+}
+
 /* init the processing run */
 void packet_range_process_init(packet_range_t *range) {
+  /* Check that, if an explicit range was selected, it's valid. */
   /* "enumeration" values */
   range->marked_range_active    = FALSE;
   range->selected_done          = FALSE;
@@ -219,7 +229,7 @@ range_process_e packet_range_process_packet(packet_range_t *range, frame_data *f
         }
         break;
     case(range_process_user_range):
-        if (value_is_in_range(&range->user_range, fdata->num) == FALSE) {
+        if (value_is_in_range(range->user_range, fdata->num) == FALSE) {
           return range_process_next;
         }
         break;
@@ -246,8 +256,21 @@ range_process_e packet_range_process_packet(packet_range_t *range, frame_data *f
 
 void packet_range_convert_str(packet_range_t *range, const gchar *es)
 {
-    /* XXX - check for errors */
-    range_convert_str(&range->user_range, es, cfile.count);
+    range_t *new_range;
+    convert_ret_t ret;
+
+    if (range->user_range != NULL)
+        g_free(range->user_range);
+    ret = range_convert_str(&new_range, es, cfile.count);
+    if (ret != CVT_NO_ERROR) {
+        /* range isn't valid */
+        range->user_range                 = NULL;
+        range->user_range_status          = ret;
+        range->user_range_cnt             = 0L;
+        range->displayed_user_range_cnt   = 0L;
+        return;
+    }
+    range->user_range = new_range;
 
     /* calculate new user specified packet range counts */
     packet_range_calc_user(range);
index 3007d215c88ad9b3f050adfd61c8d71adbd478ed..b4e9f66bc9d6e5b99558244d91a52bcd693f3a4f 100644 (file)
@@ -49,8 +49,9 @@ typedef struct packet_range_tag {
     packet_range_e  process;            /* which range to process */
     gboolean        process_filtered;   /* captured or filtered packets */
 
-    /* user specified range(s) */
-    range_t         user_range;
+    /* user specified range(s) and, if null, error status */
+    range_t         *user_range;
+    convert_ret_t   user_range_status;
 
     /* calculated values */
     guint32  selected_packet;       /* the currently selected packet */
@@ -82,8 +83,11 @@ typedef enum {
 /* init the range structure */
 extern void packet_range_init(packet_range_t *range);
 
+/* check whether the packet range is OK */
+extern convert_ret_t packet_range_check(packet_range_t *range);
+
 /* init the processing run */
-void packet_range_process_init(packet_range_t *range);
+extern void packet_range_process_init(packet_range_t *range);
 
 /* do we have to process all packets? */
 extern gboolean packet_range_process_all(packet_range_t *range);