From: Alfons Hoogervorst Date: Sun, 12 Jan 2003 22:09:09 +0000 (+0000) Subject: * AUTHORS X-Git-Tag: rel_0_8_9~54 X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=commitdiff_plain;h=639ae8d76fe1f67aacdac33f3f5faca1cabdce64 * AUTHORS add Christian Mertes * src/common/utils.[ch] g_stricase_hash(), g_stricase_equal(): functions for case insensitive hash tables * src/textview.c use top level domain names to validate email address, based on a patch by Christian Mertes (thanks!), but changed implementation to use a hash table --- diff --git a/AUTHORS b/AUTHORS index 157f47480..d1ee6aa53 100644 --- a/AUTHORS +++ b/AUTHORS @@ -167,3 +167,4 @@ contributors (beside the above; based on Changelog) Gál Zoltán Mohammed Sameer Kim Schulz + Christian Mertes diff --git a/ChangeLog.claws b/ChangeLog.claws index 3126935be..8eae00825 100644 --- a/ChangeLog.claws +++ b/ChangeLog.claws @@ -1,3 +1,15 @@ +2003-01-12 [alfons] 0.8.8claws89 + + * AUTHORS + add Christian Mertes + * src/common/utils.[ch] + g_stricase_hash(), g_stricase_equal(): functions for + case insensitive hash tables + * src/textview.c + use top level domain names to validate email address, based + on a patch by Christian Mertes (thanks!), but changed + implementation to use a hash table + 2003-01-12 [paul] 0.8.8claws88 * po/bg.po diff --git a/configure.in b/configure.in index 3c8cabe4e..bd71a1c42 100644 --- a/configure.in +++ b/configure.in @@ -11,7 +11,7 @@ MINOR_VERSION=8 MICRO_VERSION=8 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=claws88 +EXTRA_VERSION=claws89 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION dnl set $target diff --git a/src/common/utils.c b/src/common/utils.c index 3ce408aa0..57ded2b74 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -3189,3 +3189,24 @@ gchar *expand_search_string(const gchar *search_string) return returnstr; } +guint g_stricase_hash(gconstpointer gptr) +{ + guint hash_result = 0; + const char *str; + + for (str = gptr; str && *str; str++) { + if (isupper(*str)) hash_result += (*str + ' '); + else hash_result += *str; + } + + return hash_result; +} + +gint g_stricase_equal(gconstpointer gptr1, gconstpointer gptr2) +{ + const char *str1 = gptr1; + const char *str2 = gptr2; + + return !strcasecmp(str1, str2); +} + diff --git a/src/common/utils.h b/src/common/utils.h index d02b2be6f..13af7e143 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -403,4 +403,7 @@ const gchar * line_has_quote_char_last (const gchar *str, /* used in extended search */ gchar * expand_search_string (const gchar *str); +guint g_stricase_hash (gconstpointer gptr); +gint g_stricase_equal (gconstpointer gptr1, gconstpointer gptr2); + #endif /* __UTILS_H__ */ diff --git a/src/textview.c b/src/textview.c index 6c855123b..c5468a4d3 100644 --- a/src/textview.c +++ b/src/textview.c @@ -781,6 +781,63 @@ static gchar *make_uri_string(const gchar *bp, const gchar *ep) #define IS_ASCII_ALNUM(ch) (isascii(ch) && isalnum(ch)) #define IS_QUOTE(ch) ((ch) == '\'' || (ch) == '"') +static GHashTable *create_domain_tab(void) +{ + static const gchar *toplvl_domains [] = { + "museum", "aero", + "arpa", "coop", "info", "name", "biz", "com", "edu", "gov", + "int", "mil", "net", "org", "ac", "ad", "ae", "af", "ag", + "ai", "al", "am", "an", "ao", "aq", "ar", "as", "at", "au", + "aw", "az", "ba", "bb", "bd", "be", "bf", "bg", "bh", "bi", + "bj", "bm", "bn", "bo", "br", "bs", "bt", "bv", "bw", "by", + "bz", "ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", + "cm", "cn", "co", "cr", "cu", "cv", "cx", "cy", "cz", "de", + "dj", "dk", "dm", "do", "dz", "ec", "ee", "eg", "eh", "er", + "es", "et", "fi", "fj", "fk", "fm", "fo", "fr", "ga", "gd", + "ge", "gf", "gg", "gh", "gi", "gl", "gm", "gn", "gp", "gq", + "gr", "gs", "gt", "gu", "gw", "gy", "hk", "hm", "hn", "hr", + "ht", "hu", "id", "ie", "il", "im", "in", "io", "iq", "ir", + "is", "it", "je", "jm", "jo", "jp", "ke", "kg", "kh", "ki", + "km", "kn", "kp", "kr", "kw", "ky", "kz", "la", "lb", "lc", + "li", "lk", "lr", "ls", "lt", "lu", "lv", "ly", "ma", "mc", + "md", "mg", "mh", "mk", "ml", "mm", "mn", "mo", "mp", "mq", + "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz", "na", + "nc", "ne", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu", + "nz", "om", "pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm", + "pn", "pr", "ps", "pt", "pw", "py", "qa", "re", "ro", "ru", + "rw", "sa", "sb", "sc", "sd", "se", "sg", "sh", "si", "sj", + "sk", "sl", "sm", "sn", "so", "sr", "st", "sv", "sy", "sz", + "tc", "td", "tf", "tg", "th", "tj", "tk", "tm", "tn", "to", + "tp", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "uk", "um", + "us", "uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", + "wf", "ws", "ye", "yt", "yu", "za", "zm", "zw" + }; + gint n; + GHashTable *htab = g_hash_table_new(g_stricase_hash, g_stricase_equal); + + g_return_val_if_fail(htab, NULL); + for (n = 0; n < sizeof toplvl_domains / sizeof toplvl_domains[0]; n++) + g_hash_table_insert(htab, (gpointer) toplvl_domains[n], (gpointer) toplvl_domains[n]); + return htab; +} + +static gboolean is_toplvl_domain(GHashTable *tab, const gchar *first, const gchar *last) +{ + const gint MAX_LVL_DOM_NAME_LEN = 6; + gchar buf[MAX_LVL_DOM_NAME_LEN + 1]; + const gchar *m = buf + MAX_LVL_DOM_NAME_LEN + 1; + register gchar *p; + + if (last - first > MAX_LVL_DOM_NAME_LEN || first > last) + return FALSE; + + for (p = buf; p < m && first < last; *p++ = *first++) + ; + *p = 0; + + return g_hash_table_lookup(tab, buf) != NULL; +} + /* get_email_part() - retrieves an email address. Returns TRUE if succesful */ static gboolean get_email_part(const gchar *start, const gchar *scanpos, const gchar **bp, const gchar **ep) @@ -790,6 +847,9 @@ static gboolean get_email_part(const gchar *start, const gchar *scanpos, gboolean result = FALSE; const gchar *bp_ = NULL; const gchar *ep_ = NULL; + static GHashTable *dom_tab; + const gchar *last_dot = NULL; + const gchar *prelast_dot = NULL; /* the informative part of the email address (describing the name * of the email address owner) may contain quoted parts. the @@ -802,6 +862,10 @@ static gboolean get_email_part(const gchar *start, const gchar *scanpos, g_return_val_if_fail(bp != NULL, FALSE); g_return_val_if_fail(ep != NULL, FALSE); + if (!dom_tab) + dom_tab = create_domain_tab(); + g_return_val_if_fail(dom_tab, FALSE); + /* scan start of address */ for (bp_ = scanpos - 1; bp_ >= start && IS_RFC822_CHAR(*bp_); bp_--) ; @@ -814,18 +878,36 @@ static gboolean get_email_part(const gchar *start, const gchar *scanpos, if (bp_ != scanpos) { /* scan end of address */ for (ep_ = scanpos + 1; *ep_ && IS_RFC822_CHAR(*ep_); ep_++) - ; + if (*ep_ == '.') { + prelast_dot = last_dot; + last_dot = ep_; + if (*(last_dot + 1) == '.') { + if (prelast_dot == NULL) + return FALSE; + last_dot = prelast_dot; + break; + } + } /* TODO: really should terminate with an alnum? */ for (; ep_ > scanpos && !IS_ASCII_ALNUM(*ep_); --ep_) ; ep_++; - if (ep_ > scanpos + 1) { - *ep = ep_; - *bp = bp_; + if (last_dot == NULL) + return FALSE; + + if (last_dot >= ep_) + last_dot = prelast_dot; + if (last_dot == NULL) + return FALSE; + last_dot++; + + if (is_toplvl_domain(dom_tab, last_dot, ep_)) result = TRUE; - } + + *ep = ep_; + *bp = bp_; } if (!result) return FALSE;