From 4a6ceffb98a0b785494f680d3776c4bfc4052f9e Mon Sep 17 00:00:00 2001 From: "berkeviktor@aol.com" Date: Thu, 24 Feb 2011 04:14:30 +0100 Subject: add xchat r1489 --- src/common/url.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 src/common/url.c (limited to 'src/common/url.c') diff --git a/src/common/url.c b/src/common/url.c new file mode 100644 index 00000000..92aeab0a --- /dev/null +++ b/src/common/url.c @@ -0,0 +1,280 @@ +/* X-Chat + * Copyright (C) 1998 Peter Zelezny. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include "xchat.h" +#include "cfgfiles.h" +#include "fe.h" +#include "tree.h" +#include "url.h" +#ifdef HAVE_STRINGS_H +#include +#endif + +void *url_tree = NULL; + + +static int +url_free (char *url, void *data) +{ + free (url); + return TRUE; +} + +void +url_clear (void) +{ + tree_foreach (url_tree, (tree_traverse_func *)url_free, NULL); + tree_destroy (url_tree); + url_tree = NULL; +} + +static int +url_save_cb (char *url, FILE *fd) +{ + fprintf (fd, "%s\n", url); + return TRUE; +} + +void +url_save (const char *fname, const char *mode, gboolean fullpath) +{ + FILE *fd; + + if (fullpath) + fd = xchat_fopen_file (fname, mode, XOF_FULLPATH); + else + fd = xchat_fopen_file (fname, mode, 0); + if (fd == NULL) + return; + + tree_foreach (url_tree, (tree_traverse_func *)url_save_cb, fd); + fclose (fd); +} + +void +url_autosave (void) +{ + url_save ("url.save", "a", FALSE); +} + +static int +url_find (char *urltext) +{ + int pos; + + if (tree_find (url_tree, urltext, (tree_cmp_func *)strcasecmp, NULL, &pos)) + return 1; + return 0; +} + +static void +url_add (char *urltext, int len) +{ + char *data = malloc (len + 1); + if (!data) + return; + memcpy (data, urltext, len); + data[len] = 0; + + if (data[len - 1] == '.') /* chop trailing dot */ + { + len--; + data[len] = 0; + } + if (data[len - 1] == ')') /* chop trailing ) */ + data[len - 1] = 0; + + if (url_find (data)) + { + free (data); + return; + } + + if (!url_tree) + url_tree = tree_new ((tree_cmp_func *)strcasecmp, NULL); + + tree_insert (url_tree, data); + fe_url_add (data); +} + +/* check if a word is clickable. This is called on mouse motion events, so + keep it FAST! This new version was found to be almost 3x faster than + 2.4.4 release. */ + +int +url_check_word (char *word, int len) +{ +#define D(x) (x), ((sizeof (x)) - 1) + static const struct { + const char *s; + int len; + } + prefix[] = { + { D("irc.") }, + { D("ftp.") }, + { D("www.") }, + { D("irc://") }, + { D("ftp://") }, + { D("http://") }, + { D("https://") }, + { D("file://") }, + { D("rtsp://") }, + { D("ut2004://") }, + }, + suffix[] = { + { D(".org") }, + { D(".net") }, + { D(".com") }, + { D(".edu") }, + { D(".html") }, + { D(".info") }, + { D(".name") }, + }; +#undef D + const char *at, *dot; + int i, dots; + + if (len > 1 && word[1] == '#' && strchr("@+^%*#", word[0])) + return WORD_CHANNEL; + + if ((word[0] == '#' || word[0] == '&') && word[1] != '#' && word[1] != 0) + return WORD_CHANNEL; + + for (i = 0; i < G_N_ELEMENTS(prefix); i++) + { + int l; + + l = prefix[i].len; + if (len > l) + { + int j; + + /* This is pretty much strncasecmp(). */ + for (j = 0; j < l; j++) + { + unsigned char c = word[j]; + if (tolower(c) != prefix[i].s[j]) + break; + } + if (j == l) + return WORD_URL; + } + } + + at = strchr (word, '@'); /* check for email addy */ + dot = strrchr (word, '.'); + if (at && dot) + { + if (at < dot) + { + if (strchr (word, '*')) + return WORD_HOST; + else + return WORD_EMAIL; + } + } + + /* check if it's an IP number */ + dots = 0; + for (i = 0; i < len; i++) + { + if (word[i] == '.' && i > 0) + dots++; /* allow 127.0.0.1:80 */ + else if (!isdigit ((unsigned char) word[i]) && word[i] != ':') + { + dots = 0; + break; + } + } + if (dots == 3) + return WORD_HOST; + + if (len > 5) + { + for (i = 0; i < G_N_ELEMENTS(suffix); i++) + { + int l; + + l = suffix[i].len; + if (len > l) + { + const unsigned char *p = &word[len - l]; + int j; + + /* This is pretty much strncasecmp(). */ + for (j = 0; j < l; j++) + { + if (tolower(p[j]) != suffix[i].s[j]) + break; + } + if (j == l) + return WORD_HOST; + } + } + + if (word[len - 3] == '.' && + isalpha ((unsigned char) word[len - 2]) && + isalpha ((unsigned char) word[len - 1])) + return WORD_HOST; + } + + return 0; +} + +void +url_check_line (char *buf, int len) +{ + char *po = buf; + char *start; + int wlen; + + if (buf[0] == ':' && buf[1] != 0) + po++; + + start = po; + + /* check each "word" (space separated) */ + while (1) + { + switch (po[0]) + { + case 0: + case ' ': + wlen = po - start; + if (wlen > 2) + { + if (url_check_word (start, wlen) == WORD_URL) + { + url_add (start, wlen); + } + } + if (po[0] == 0) + return; + po++; + start = po; + break; + + default: + po++; + } + } +} -- cgit 1.4.1