fix merge conflict

This commit is contained in:
TingPing 2013-06-18 20:40:07 -04:00
commit 64ba92593e
4 changed files with 181 additions and 70 deletions

View File

@ -35,6 +35,7 @@ GTree *url_btree = NULL;
static int do_an_re (const char *word, int *start, int *end, int *type); static int do_an_re (const char *word, int *start, int *end, int *type);
static GRegex *re_url (void); static GRegex *re_url (void);
static GRegex *re_host (void); static GRegex *re_host (void);
static GRegex *re_host6 (void);
static GRegex *re_email (void); static GRegex *re_email (void);
static GRegex *re_nick (void); static GRegex *re_nick (void);
static GRegex *re_channel (void); static GRegex *re_channel (void);
@ -222,6 +223,7 @@ url_check_word (const char *word)
/* Fall through */ /* Fall through */
case WORD_URL: case WORD_URL:
case WORD_HOST: case WORD_HOST:
case WORD_HOST6:
case WORD_CHANNEL: case WORD_CHANNEL:
case WORD_PATH: case WORD_PATH:
return lasttype; return lasttype;
@ -314,9 +316,10 @@ do_an_re(const char *word,int *start, int *end, int *type)
} func_t; } func_t;
func_t funcs[] = func_t funcs[] =
{ {
{ re_email, WORD_EMAIL },
{ re_url, WORD_URL }, { re_url, WORD_URL },
{ re_email, WORD_EMAIL },
{ re_channel, WORD_CHANNEL }, { re_channel, WORD_CHANNEL },
{ re_host6, WORD_HOST6 },
{ re_host, WORD_HOST }, { re_host, WORD_HOST },
{ re_path, WORD_PATH }, { re_path, WORD_PATH },
{ re_nick, WORD_NICK } { re_nick, WORD_NICK }
@ -349,17 +352,23 @@ do_an_re(const char *word,int *start, int *end, int *type)
/* Miscellaneous description --- */ /* Miscellaneous description --- */
#define DOMAIN "[a-z0-9][-a-z0-9]*(\\.[-a-z0-9]+)*\\." #define DOMAIN "[a-z0-9][-a-z0-9]*(\\.[-a-z0-9]+)*\\."
#define TLD "[a-z][-a-z0-9]*[a-z]" #define TLD "[a-z][-a-z0-9]*[a-z]"
#define IPADDR "[0-9]+(\\.[0-9]+){3}" #define IPADDR "[0-9]{1,3}(\\.[0-9]{1,3}){3}"
#define HOST "(" DOMAIN TLD "|" IPADDR ")" #define IPV6GROUP "([0-9a-f]{0,4})"
#define OPT_PORT "(:[1-9][0-9]{0,4})?" #define IPV6ADDR "((" IPV6GROUP "(:" IPV6GROUP "){7})" \
"|(" IPV6GROUP "(:" IPV6GROUP ")*:(:" IPV6GROUP ")+))" /* with :: compression */
#define HOST "(" DOMAIN TLD "|" IPADDR "|" IPV6ADDR ")"
/* In urls the IPv6 must be enclosed in square brackets */
#define HOST_URL "(" DOMAIN TLD "|" IPADDR "|" "\\[" IPV6ADDR "\\]" ")"
#define PORT "(:[1-9][0-9]{0,4})"
#define OPT_PORT "(" PORT ")?"
GRegex * GRegex *
make_re(char *grist, char *type) make_re (char *grist)
{ {
GRegex *ret; GRegex *ret;
GError *err = NULL; GError *err = NULL;
ret = g_regex_new (grist, G_REGEX_CASELESS + G_REGEX_OPTIMIZE, 0, &err); ret = g_regex_new (grist, G_REGEX_CASELESS | G_REGEX_OPTIMIZE, 0, &err);
g_free (grist); g_free (grist);
return ret; return ret;
} }
@ -375,78 +384,163 @@ re_host (void)
if (host_ret) return host_ret; if (host_ret) return host_ret;
grist = g_strdup_printf ( grist = g_strdup_printf (
"(" /* HOST */ "("
HOST OPT_PORT "(" HOST_URL PORT ")|(" HOST ")"
")" ")"
); );
host_ret = make_re (grist, "re_host"); host_ret = make_re (grist);
return host_ret; return host_ret;
} }
static GRegex *
re_host6 (void)
{
static GRegex *host6_ret;
char *grist;
if (host6_ret) return host6_ret;
grist = g_strdup_printf (
"("
"(" IPV6ADDR ")|(" "\\[" IPV6ADDR "\\]" PORT ")"
")"
);
host6_ret = make_re (grist);
return host6_ret;
}
/* URL description --- */ /* URL description --- */
#define SCHEME "(%s)" #define SCHEME "(%s)"
#define LPAR "\\(" #define LPAR "\\("
#define RPAR "\\)" #define RPAR "\\)"
#define NOPARENS "[^() \t]*" #define NOPARENS "[^() \t]*"
#define PATH \
"(" \
"(" LPAR NOPARENS RPAR ")" \
"|" \
"(" NOPARENS ")" \
")*" /* Zero or more occurrences of either of these */ \
"(?<![.,?!\\]])" /* Not allowed to end with these */
#define USERINFO "([-a-z0-9._~%]+(:[-a-z0-9._~%]*)?@)"
char *prefix[] = { /* Flags used to describe URIs (RFC 3986)
"irc\\.", *
"ftp\\.", * Bellow is an example of what the flags match.
"www\\.", *
"irc://", * URI_AUTHORITY - http://example.org:80/foo/bar
"ircs://", * ^^^^^^^^^^^^^^^^
"ftp://", * URI_USERINFO/URI_OPT_USERINFO - http://user@example.org:80/foo/bar
"http://", * ^^^^^
"https://", * URI_PATH - http://example.org:80/foo/bar
"file://", * ^^^^^^^^
"rtsp://", */
NULL #define URI_AUTHORITY (1 << 0)
#define URI_OPT_USERINFO (1 << 1)
#define URI_USERINFO (1 << 2)
#define URI_PATH (1 << 3)
struct
{
const char *scheme; /* scheme name. e.g. http */
const char *path_sep; /* string that begins the path */
int flags; /* see above (flag macros) */
} uri[] = {
{ "irc", "/", URI_PATH },
{ "ircs", "/", URI_PATH },
{ "rtsp", "/", URI_AUTHORITY | URI_PATH },
{ "feed", "/", URI_AUTHORITY | URI_PATH },
{ "teamspeak", "?", URI_AUTHORITY | URI_PATH },
{ "ftp", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "sftp", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "ftps", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "http", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "https", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "cvs", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "svn", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "git", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "bzr", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "rsync", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "mumble", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "ventrilo", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "xmpp", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "h323", ";", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "imap", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "pop", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "nfs", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "smb", "/", URI_AUTHORITY | URI_OPT_USERINFO | URI_PATH },
{ "ssh", "", URI_AUTHORITY | URI_OPT_USERINFO },
{ "sip", "", URI_AUTHORITY | URI_USERINFO },
{ "sips", "", URI_AUTHORITY | URI_USERINFO },
{ "magnet", "?", URI_PATH },
{ "mailto", "", URI_PATH },
{ "bitcoin", "", URI_PATH },
{ "gtalk", "", URI_PATH },
{ "steam", "", URI_PATH },
{ "file", "/", URI_PATH },
{ "callto", "", URI_PATH },
{ "skype", "", URI_PATH },
{ "geo", "", URI_PATH },
{ NULL, "", 0}
}; };
static GRegex * static GRegex *
re_url (void) re_url (void)
{ {
static GRegex *url_ret; static GRegex *url_ret = NULL;
GString *grist_gstr;
char *grist; char *grist;
char *scheme; int i;
if (url_ret) return url_ret; if (url_ret) return url_ret;
scheme = g_strjoinv ("|", prefix); grist_gstr = g_string_new (NULL);
grist = g_strdup_printf (
"(" /* URL or HOST */ /* Add regex "host/path", representing a "schemeless" url */
"(" g_string_append (grist_gstr, "(" HOST_URL OPT_PORT "/" "(" PATH ")?" ")");
SCHEME HOST OPT_PORT
"(" /* Optional "/path?query_string#fragment_id" */ for (i = 0; uri[i].scheme; i++)
"/" /* Must start with slash */ {
"(" g_string_append (grist_gstr, "|(");
"(" LPAR NOPARENS RPAR ")" g_string_append_printf (grist_gstr, "%s:", uri[i].scheme);
"|"
"(" NOPARENS ")" if (uri[i].flags & URI_AUTHORITY)
")*" /* Zero or more occurrences of either of these */ g_string_append (grist_gstr, "//");
"(?<![.,?!\\]])" /* Not allowed to end with these */
")?" /* Zero or one of this /path?query_string#fragment_id thing */ if (uri[i].flags & URI_USERINFO)
")|(" g_string_append (grist_gstr, USERINFO);
HOST OPT_PORT "/" else if (uri[i].flags & URI_OPT_USERINFO)
"(" /* Optional "path?query_string#fragment_id" */ g_string_append (grist_gstr, USERINFO "?");
"("
"(" LPAR NOPARENS RPAR ")" if (uri[i].flags & URI_AUTHORITY)
"|" g_string_append (grist_gstr, HOST_URL OPT_PORT);
"(" NOPARENS ")"
")*" /* Zero or more occurrences of either of these */ if (uri[i].flags & URI_PATH)
"(?<![.,?!\\]])" /* Not allowed to end with these */ {
")?" /* Zero or one of this /path?query_string#fragment_id thing */ char *sep_escaped;
")"
")" sep_escaped = g_regex_escape_string (uri[i].path_sep,
, scheme strlen(uri[i].path_sep));
);
url_ret = make_re (grist, "re_url"); g_string_append_printf(grist_gstr, "(" "%s" PATH ")?",
g_free (scheme); sep_escaped);
g_free(sep_escaped);
}
g_string_append(grist_gstr, ")");
}
grist = g_string_free (grist_gstr, FALSE);
url_ret = make_re (grist);
return url_ret; return url_ret;
} }
/* EMAIL description --- */ /* EMAIL description --- */
#define EMAIL "[a-z][-_a-z0-9]+@" "(" HOST ")" #define EMAIL "[a-z][-_a-z0-9]+@" "(" HOST_URL ")"
static GRegex * static GRegex *
re_email (void) re_email (void)
@ -457,11 +551,11 @@ re_email (void)
if (email_ret) return email_ret; if (email_ret) return email_ret;
grist = g_strdup_printf ( grist = g_strdup_printf (
"(" /* EMAIL */ "("
EMAIL EMAIL
")" ")"
); );
email_ret = make_re (grist, "re_email"); email_ret = make_re (grist);
return email_ret; return email_ret;
} }
@ -493,11 +587,11 @@ re_nick (void)
if (nick_ret) return nick_ret; if (nick_ret) return nick_ret;
grist = g_strdup_printf ( grist = g_strdup_printf (
"(" /* NICK */ "("
NICK NICK
")" ")"
); );
nick_ret = make_re (grist, "re_nick"); nick_ret = make_re (grist);
return nick_ret; return nick_ret;
} }
@ -513,21 +607,21 @@ re_channel (void)
if (channel_ret) return channel_ret; if (channel_ret) return channel_ret;
grist = g_strdup_printf ( grist = g_strdup_printf (
"(" /* CHANNEL */ "("
CHANNEL CHANNEL
")" ")"
); );
channel_ret = make_re (grist, "re_channel"); channel_ret = make_re (grist);
return channel_ret; return channel_ret;
} }
/* PATH description --- */ /* PATH description --- */
#ifdef WIN32 #ifdef WIN32
/* Windows path can be .\ ..\ or C: D: etc */ /* Windows path can be .\ ..\ or C: D: etc */
#define PATH "^(\\.{1,2}\\\\|[a-z]:).*" #define FS_PATH "^(\\.{1,2}\\\\|[a-z]:).*"
#else #else
/* Linux path can be / or ./ or ../ etc */ /* Linux path can be / or ./ or ../ etc */
#define PATH "^(/|\\./|\\.\\./).*" #define FS_PATH "^(/|\\./|\\.\\./).*"
#endif #endif
static GRegex * static GRegex *
@ -539,10 +633,10 @@ re_path (void)
if (path_ret) return path_ret; if (path_ret) return path_ret;
grist = g_strdup_printf ( grist = g_strdup_printf (
"(" /* PATH */ "("
PATH FS_PATH
")" ")"
); );
path_ret = make_re (grist, "re_path"); path_ret = make_re (grist);
return path_ret; return path_ret;
} }

View File

@ -26,7 +26,8 @@ extern void *url_tree;
#define WORD_NICK 2 #define WORD_NICK 2
#define WORD_CHANNEL 3 #define WORD_CHANNEL 3
#define WORD_HOST 4 #define WORD_HOST 4
#define WORD_EMAIL 5 #define WORD_HOST6 5
#define WORD_EMAIL 6
/* anything >0 will be displayed as a link by gtk_xtext_motion_notify() */ /* anything >0 will be displayed as a link by gtk_xtext_motion_notify() */
#define WORD_DIALOG -1 #define WORD_DIALOG -1
#define WORD_PATH -2 #define WORD_PATH -2

View File

@ -1008,11 +1008,13 @@ fe_open_url_inner (const char *url)
static void static void
fe_open_url_locale (const char *url) fe_open_url_locale (const char *url)
{ {
if (url_check_word (url) == WORD_PATH) int url_type = url_check_word (url);
{
#ifndef WIN32
char *uri; char *uri;
/* gvfs likes file:// */
if (url_type == WORD_PATH)
{
#ifndef WIN32
uri = g_strconcat ("file://", url, NULL); uri = g_strconcat ("file://", url, NULL);
fe_open_url_inner (uri); fe_open_url_inner (uri);
g_free (uri); g_free (uri);
@ -1020,6 +1022,18 @@ fe_open_url_locale (const char *url)
fe_open_url_inner (url); fe_open_url_inner (url);
#endif #endif
} }
/* IPv6 addr. Add http:// */
else if (url_type == WORD_HOST6)
{
/* IPv6 addrs in urls should be enclosed in [ ] */
if (*url != '[')
uri = g_strdup_printf ("http://[%s]", url);
else
uri = g_strdup_printf ("http://%s", url);
fe_open_url_inner (uri);
g_free (uri);
}
/* the http:// part's missing, prepend it, otherwise it won't always work */ /* the http:// part's missing, prepend it, otherwise it won't always work */
else if (strchr (url, ':') == NULL) else if (strchr (url, ':') == NULL)
{ {

View File

@ -2267,6 +2267,7 @@ mg_word_clicked (GtkWidget *xtext, char *word, GdkEventButton *even)
switch (word_type) switch (word_type)
{ {
case WORD_URL: case WORD_URL:
case WORD_HOST6:
case WORD_HOST: case WORD_HOST:
word[end] = 0; word[end] = 0;
fe_open_url (word + start); fe_open_url (word + start);
@ -2293,6 +2294,7 @@ mg_word_clicked (GtkWidget *xtext, char *word, GdkEventButton *even)
menu_middlemenu (sess, even); menu_middlemenu (sess, even);
break; break;
case WORD_URL: case WORD_URL:
case WORD_HOST6:
case WORD_HOST: case WORD_HOST:
word[end] = 0; word[end] = 0;
word += start; word += start;