diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp
index 6157a53f..9d0c39a0 100644
--- a/backends/libpurple/main.cpp
+++ b/backends/libpurple/main.cpp
@@ -95,6 +95,253 @@ static GHashTable *spectrum_ui_get_info(void)
return ui_info;
}
+static gboolean
+badchar(char c)
+{
+ switch (c) {
+ case ' ':
+ case ',':
+ case '\0':
+ case '\n':
+ case '\r':
+ case '<':
+ case '>':
+ case '"':
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static gboolean
+badentity(const char *c)
+{
+ if (!g_ascii_strncasecmp(c, "<", 4) ||
+ !g_ascii_strncasecmp(c, ">", 4) ||
+ !g_ascii_strncasecmp(c, """, 6)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static const char *
+process_link(GString *ret,
+ const char *start, const char *c,
+ int matchlen,
+ const char *urlprefix,
+ int inside_paren)
+{
+ char *url_buf;
+ const char *t;
+
+ for (t = c;; t++) {
+ if (!badchar(*t) && !badentity(t))
+ continue;
+
+ if (t - c == matchlen)
+ break;
+
+ if (*t == ',' && *(t + 1) != ' ') {
+ continue;
+ }
+
+ if (t > start && *(t - 1) == '.')
+ t--;
+ if (t > start && *(t - 1) == ')' && inside_paren > 0)
+ t--;
+
+ url_buf = g_strndup(c, t - c);
+// tmpurlbuf = purple_unescape_html(url_buf);
+// std::cout << url_buf << "\n";
+ g_string_append_printf(ret, "%s",
+ urlprefix,
+ url_buf, url_buf);
+// g_free(tmpurlbuf);
+ g_free(url_buf);
+ return t;
+ }
+
+ return c;
+}
+
+static char *
+spectrum_markup_linkify(const char *text)
+{
+ const char *c, *t, *q = NULL;
+ char *tmpurlbuf, *url_buf;
+ gunichar g;
+ gboolean inside_html = FALSE;
+ int inside_paren = 0;
+ GString *ret;
+
+ if (text == NULL)
+ return NULL;
+
+ ret = g_string_new("");
+
+ c = text;
+ while (*c) {
+
+ if(*c == '(' && !inside_html) {
+ inside_paren++;
+ ret = g_string_append_c(ret, *c);
+ c++;
+ }
+
+ if(inside_html) {
+ if(*c == '>') {
+ inside_html = FALSE;
+ } else if(!q && (*c == '\"' || *c == '\'')) {
+ q = c;
+ } else if(q) {
+ if(*c == *q)
+ q = NULL;
+ }
+ } else if(*c == '<') {
+ inside_html = TRUE;
+ if (!g_ascii_strncasecmp(c, "", 3)) {
+ inside_html = FALSE;
+ break;
+ }
+ ret = g_string_append_c(ret, *c);
+ c++;
+ if (!(*c))
+ break;
+ }
+ }
+ } else if (!g_ascii_strncasecmp(c, "http://", 7)) {
+ c = process_link(ret, text, c, 7, "", inside_paren);
+ } else if (!g_ascii_strncasecmp(c, "https://", 8)) {
+ c = process_link(ret, text, c, 8, "", inside_paren);
+ } else if (!g_ascii_strncasecmp(c, "ftp://", 6)) {
+ c = process_link(ret, text, c, 6, "", inside_paren);
+ } else if (!g_ascii_strncasecmp(c, "sftp://", 7)) {
+ c = process_link(ret, text, c, 7, "", inside_paren);
+ } else if (!g_ascii_strncasecmp(c, "file://", 7)) {
+ c = process_link(ret, text, c, 7, "", inside_paren);
+ } else if (!g_ascii_strncasecmp(c, "www.", 4) && c[4] != '.' && (c == text || badchar(c[-1]) || badentity(c-1))) {
+ c = process_link(ret, text, c, 4, "http://", inside_paren);
+ } else if (!g_ascii_strncasecmp(c, "ftp.", 4) && c[4] != '.' && (c == text || badchar(c[-1]) || badentity(c-1))) {
+ c = process_link(ret, text, c, 4, "ftp://", inside_paren);
+ } else if (!g_ascii_strncasecmp(c, "xmpp:", 5) && (c == text || badchar(c[-1]) || badentity(c-1))) {
+ c = process_link(ret, text, c, 5, "", inside_paren);
+ } else if (!g_ascii_strncasecmp(c, "mailto:", 7)) {
+ t = c;
+ while (1) {
+ if (badchar(*t) || badentity(t)) {
+ const char *d;
+ if (t - c == 7) {
+ break;
+ }
+ if (t > text && *(t - 1) == '.')
+ t--;
+ if ((d = strstr(c + 7, "?")) != NULL && d < t)
+ url_buf = g_strndup(c + 7, d - c - 7);
+ else
+ url_buf = g_strndup(c + 7, t - c - 7);
+ if (!purple_email_is_valid(url_buf)) {
+ g_free(url_buf);
+ break;
+ }
+ g_free(url_buf);
+ url_buf = g_strndup(c, t - c);
+// tmpurlbuf = purple_unescape_html(url_buf);
+ g_string_append_printf(ret, "%s",
+ url_buf, url_buf);
+ g_free(url_buf);
+// g_free(tmpurlbuf);
+ c = t;
+ break;
+ }
+ t++;
+ }
+ } else if (c != text && (*c == '@')) {
+ int flag;
+ GString *gurl_buf = NULL;
+ const char illegal_chars[] = "!@#$%^&*()[]{}/|\\<>\":;\r\n \0";
+
+ if (strchr(illegal_chars,*(c - 1)) || strchr(illegal_chars, *(c + 1)))
+ flag = 0;
+ else {
+ flag = 1;
+ gurl_buf = g_string_new("");
+ }
+
+ t = c;
+ while (flag) {
+ /* iterate backwards grabbing the local part of an email address */
+ g = g_utf8_get_char(t);
+ if (badchar(*t) || (g >= 127) || (*t == '(') ||
+ ((*t == ';') && ((t > (text+2) && (!g_ascii_strncasecmp(t - 3, "<", 4) ||
+ !g_ascii_strncasecmp(t - 3, ">", 4))) ||
+ (t > (text+4) && (!g_ascii_strncasecmp(t - 5, """, 6)))))) {
+ /* local part will already be part of ret, strip it out */
+ ret = g_string_truncate(ret, ret->len - (c - t));
+ ret = g_string_append_unichar(ret, g);
+ break;
+ } else {
+ g_string_prepend_unichar(gurl_buf, g);
+ t = g_utf8_find_prev_char(text, t);
+ if (t < text) {
+ ret = g_string_assign(ret, "");
+ break;
+ }
+ }
+ }
+
+ t = g_utf8_find_next_char(c, NULL);
+
+ while (flag) {
+ /* iterate forwards grabbing the domain part of an email address */
+ g = g_utf8_get_char(t);
+ if (badchar(*t) || (g >= 127) || (*t == ')') || badentity(t)) {
+ char *d;
+
+ url_buf = g_string_free(gurl_buf, FALSE);
+
+ /* strip off trailing periods */
+ if (strlen(url_buf) > 0) {
+ for (d = url_buf + strlen(url_buf) - 1; *d == '.'; d--, t--)
+ *d = '\0';
+ }
+
+ tmpurlbuf = purple_unescape_html(url_buf);
+ if (purple_email_is_valid(tmpurlbuf)) {
+ g_string_append_printf(ret, "%s",
+ url_buf, url_buf);
+ } else {
+ g_string_append(ret, url_buf);
+ }
+ g_free(url_buf);
+ g_free(tmpurlbuf);
+ c = t;
+
+ break;
+ } else {
+ g_string_append_unichar(gurl_buf, g);
+ t = g_utf8_find_next_char(t, NULL);
+ }
+ }
+ }
+
+ if(*c == ')' && !inside_html) {
+ inside_paren--;
+ ret = g_string_append_c(ret, *c);
+ c++;
+ }
+
+ if (*c == 0)
+ break;
+
+ ret = g_string_append_c(ret, *c);
+ c++;
+
+ }
+ return g_string_free(ret, FALSE);
+}
+
struct authRequest {
PurpleAccountRequestAuthorizationCb authorize_cb;
PurpleAccountRequestAuthorizationCb deny_cb;
@@ -767,7 +1014,7 @@ static void conv_write_im(PurpleConversation *conv, const char *who, const char
char *newline = purple_strdup_withhtml(msg);
char *strip, *xhtml, *xhtml_linkified;
purple_markup_html_to_xhtml(newline, &xhtml, &strip);
- xhtml_linkified = purple_markup_linkify(xhtml);
+ xhtml_linkified = spectrum_markup_linkify(xhtml);
std::string message_(strip);
std::string xhtml_(xhtml_linkified);
diff --git a/spectrum/src/sample.cfg b/spectrum/src/sample.cfg
index 4fa7ed22..7bd97004 100644
--- a/spectrum/src/sample.cfg
+++ b/spectrum/src/sample.cfg
@@ -11,7 +11,7 @@ admin_password=test
#cert=server.pfx #patch to PKCS#12 certificate
#cert_password=test #password to that certificate if any
users_per_backend=10
-backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum_libpurple_backend
+backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend
#backend=/home/hanzz/code/libtransport/backends/frotz/spectrum_frotz_backend
#backend=../../backends/libircclient-qt/spectrum_libircclient-qt_backend
#protocol=prpl-msn