view util.c @ 332:227852ee649c

do not append "in_reply_to_status_id" when msdid is 0.
author Yoshiki Yazawa <[email protected]>
date Tue, 13 Oct 2009 03:10:32 +0900
parents b4c846870b3c
children 9f78fb6bfc76
line wrap: on
line source

#include "pidgin-twitter.h"

extern GRegex *regp[];
extern guint64 reply_to_msgid;
extern PurpleAccount *account_for_twitter;

/* prototypes */
static gchar *twitter_memrchr(const gchar *s, int c, size_t n);
void fav_with_api(guint64 id);


/* functions */

/* this function has been taken from autoaccept plugin */
gboolean
ensure_path_exists(const char *dir)
{
	if (!g_file_test(dir, G_FILE_TEST_IS_DIR)) {
		if (purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR))
			return FALSE;
	}

	return TRUE;
}

static gchar *
twitter_memrchr(const gchar *s, int c, size_t n)
{
    int nn = n;

    g_return_val_if_fail(s != NULL, NULL);

    while(nn+1) {
        if((int)*(s+nn) == c)
            return (gchar *)(s+nn);
        nn--;
    }
    return NULL;
}

static gchar *html_tags[] = {
    "<a ",
    "</a>",
    "<b>",
    "</b>",
    "<p>",
    "</p>",
    "<div ",
    "</div>",
    "<span ",
    "</span>",
    "<body>",
    "<body ",
    "</body>",
    "<i>",
    "</i>",
    "<font ",
    "</font>",
    "<br>",
    "<br/>",
    "<img ",
    "<html>",
    "<html ",
    "</html>",
    NULL
};

gchar *
strip_html_markup(const gchar *src)
{
    gchar *head, *tail;     /* head and tail of html */
    gchar *begin, *end;     /* begin:<  end:> */
    gchar *html, *str;      /* copied src and string to be returned */
/*    gchar *vis1, *vis2; */     /* begin and end of address part */
    gchar *startp;          /* starting point marker */
    gchar **tagp;           /* tag iterator */
    gchar *tmp, *tmp2;      /* scratches */

    g_return_val_if_fail(src != NULL, NULL);

    const gchar *ptr, *ent;
    gchar *ptr2;
    gint srclen;
    gint entlen;

    /* unescape &x; */
    srclen = strlen(src);
    html = g_malloc0(srclen + 1);
    ptr2 = html;
    for(ptr = src; *ptr; ) {
        if(*ptr == '&') {
            ent = purple_markup_unescape_entity(ptr, &entlen);
            if(ent != NULL) {
                while(*ent) {
                    if(ptr2 - html < srclen)
                        *ptr2++ = *ent++;
                    else
                        ent++;
                }
                ptr += entlen;
            }
            else {
                if(ptr2 - html < srclen)
                    *ptr2++ = *ptr++;
                else
                    ptr++;
            }
        }
        else {
            if(ptr2 - html < srclen)
                *ptr2++ = *ptr++;
            else
                ptr++;
        }
    } /* for */

    str = g_strdup("\0");

    head = html;
    tail = head + strlen(html);
    startp = head;

loop:
    begin = NULL;
    end = NULL;

    if(startp >= tail) {
        g_free(html);
        return str;
    }

    end = strchr(startp, '>');
    if(end) {
        begin = twitter_memrchr(startp, '<', end - startp);
        if(begin < startp)
            begin = NULL;

        if(!begin) { /* '>' found but no corresponding '<' */
            tmp = g_strndup(startp, end - startp + 1); /* concat until '>' */
            tmp2 = g_strconcat(str, tmp, NULL);
            g_free(str);
            g_free(tmp);
            str = tmp2;
            startp = end + 1;
            goto loop;
        }
    }
    else { /* neither '>' nor '<' were found */
        tmp = g_strconcat(str, startp, NULL); /* concat the rest */
        g_free(str);
        str = tmp;
        g_free(html);
        return str;
    }

    /* here, both < and > are found */
    /* concatenate leading part to dest */
    tmp = g_strndup(startp, begin - startp);
    tmp2 = g_strconcat(str, tmp, NULL);
    g_free(tmp);
    g_free(str);
    str = tmp2;

    /* find tag */
    for(tagp = html_tags; *tagp; tagp++) {
        if(!g_ascii_strncasecmp(begin, *tagp, strlen(*tagp))) {
            /* we found a valid tag */
            /* if tag is <a href=, extract address. */
#if 0
            if(!strcmp(*tagp, "<a href=")) {
                vis1 = NULL; vis2 = NULL;

                vis1 = strchr(begin, '\'');
                if(vis1)
                    vis2 = strchr(vis1+1, '\'');
                if(!vis1) {
                    vis1 = strchr(begin, '\"');
                    if(vis1)
                        vis2 = strchr(vis1+1, '\"');
                }
                if(vis1 && vis2) {
                    *vis2 = '\0';
                    /* generate "[ http://example.com/ ] anchor " */
                    tmp = g_strconcat(str, "[ ", vis1+1, " ]", " ", NULL);
                    g_free(str);
                    str = tmp;
                }
                startp = end + 1;
                goto loop;
            } /* <a href= */
            else {
                /* anything else: discard whole <>. */
                startp = end + 1;
                goto loop;
            }
#else
            /* anything else: discard whole <>. */
            startp = end + 1;
            goto loop;
#endif
        }  /* valid tag */
    }

    /* no valid tag was found: copy <brabra> */
    tmp = g_strndup(begin, end - begin + 1);
    tmp2 = g_strconcat(str, tmp, NULL);
    g_free(tmp);
    g_free(str);
    str = tmp2;
    startp = end + 1;
    goto loop;
}

/* string utilities */
void
escape(gchar **str)
{
    GMatchInfo *match_info = NULL;
    gchar *newstr = NULL, *match = NULL;
    gboolean flag = FALSE;

    /* search genuine command */
    g_regex_match(regp[COMMAND], *str, 0, &match_info);
    while(g_match_info_matches(match_info)) {
        match = g_match_info_fetch(match_info, 1);
        twitter_debug("command = %s\n", match);
        g_free(match);
        g_match_info_next(match_info, NULL);
        flag = TRUE;
    }
    g_match_info_free(match_info);
    match_info = NULL;

    if(flag)
        return;

    /* if not found, check pseudo command */
    g_regex_match(regp[PSEUDO], *str, 0, &match_info);
    while(g_match_info_matches(match_info)) {
        match = g_match_info_fetch(match_info, 1);
        twitter_debug("pseudo = %s\n", match);
        g_free(match);
        g_match_info_next(match_info, NULL);
        flag = TRUE;
    }
    g_match_info_free(match_info);
    match_info = NULL;

    /* if there is pseudo one, escape it */
    if(flag) {
        /* put ". " to the beginning of buffer */
        newstr = g_strdup_printf(". %s", *str);
        twitter_debug("*str = %s newstr = %s\n", *str, newstr);
        g_free(*str);
        *str = newstr;
    }
}

void
strip_markup(gchar **str, gboolean escape)
{
    gchar *plain;

    plain = strip_html_markup(*str);
    g_free(*str);
    if(escape) {
        *str = g_markup_escape_text(plain, -1);
        g_free(plain);
    }
    else {
        *str = plain;
    }
    twitter_debug("result=%s\n", *str);
}

gboolean
is_twitter_account(PurpleAccount *account, const char *name)
{
    const gchar *proto = purple_account_get_protocol_id(account);

    if(g_strstr_len(name,  19, "[email protected]") &&
       g_strstr_len(proto, 11, "prpl-jabber")) {
        return TRUE;
    }

    return FALSE;
}

gboolean
is_twitter_conv(PurpleConversation *conv)
{
    g_return_val_if_fail(conv != NULL, FALSE);

    const char *name = purple_conversation_get_name(conv);
    PurpleAccount *account = purple_conversation_get_account(conv);

    return is_twitter_account(account, name);
}

gboolean
is_wassr_account(PurpleAccount *account, const char *name)
{
    const gchar *proto = purple_account_get_protocol_id(account);

    if(g_strstr_len(name,  18, "[email protected]") &&
       g_strstr_len(proto, 11, "prpl-jabber")) {
        return TRUE;
    }

    return FALSE;
}

gboolean
is_wassr_conv(PurpleConversation *conv)
{
    g_return_val_if_fail(conv != NULL, FALSE);

    const char *name = purple_conversation_get_name(conv);
    PurpleAccount *account = purple_conversation_get_account(conv);

    return is_wassr_account(account, name);
}

gboolean
is_identica_account(PurpleAccount *account, const char *name)
{
    const gchar *proto = purple_account_get_protocol_id(account);

    if(g_strstr_len(name,  16, "[email protected]") &&
       g_strstr_len(proto, 11, "prpl-jabber")) {
        return TRUE;
    }

    return FALSE;
}

gboolean
is_identica_conv(PurpleConversation *conv)
{
    g_return_val_if_fail(conv != NULL, FALSE);

    const char *name = purple_conversation_get_name(conv);
    PurpleAccount *account = purple_conversation_get_account(conv);

    return is_identica_account(account, name);
}

gboolean
is_jisko_account(PurpleAccount *account, const char *name)
{
    const gchar *proto = purple_account_get_protocol_id(account);

    if(g_strstr_len(name,  16, "[email protected]") &&
       g_strstr_len(proto, 11, "prpl-jabber")) {
        return TRUE;
    }

    return FALSE;
}

gboolean
is_jisko_conv(PurpleConversation *conv)
{
    g_return_val_if_fail(conv != NULL, FALSE);

    const char *name = purple_conversation_get_name(conv);
    PurpleAccount *account = purple_conversation_get_account(conv);

    return is_jisko_account(account, name);
}

gboolean
is_ffeed_account(PurpleAccount *account, const char *name)
{
    const gchar *proto = purple_account_get_protocol_id(account);

    if(g_strstr_len(name,  22, "[email protected]") &&
       g_strstr_len(proto, 11, "prpl-jabber")) {
        return TRUE;
    }

    return FALSE;
}

gboolean
is_ffeed_conv(PurpleConversation *conv)
{
    g_return_val_if_fail(conv != NULL, FALSE);

    const char *name = purple_conversation_get_name(conv);
    PurpleAccount *account = purple_conversation_get_account(conv);

    return is_ffeed_account(account, name);
}

gint
get_service_type_by_account(PurpleAccount *account, const char *sender)
{
    gint service = unknown_service;

    g_return_val_if_fail(account != NULL, unknown_service);
    g_return_val_if_fail(sender != NULL, unknown_service);

    if(is_twitter_account(account, sender))
        service = twitter_service;
    else if(is_wassr_account(account, sender))
        service = wassr_service;
    else if(is_identica_account(account, sender))
        service = identica_service;
    else if(is_jisko_account(account, sender))
        service = jisko_service;
    else if(is_ffeed_account(account, sender))
        service = ffeed_service;

    return service;
}

gint
get_service_type(PurpleConversation *conv)
{
    gint service = unknown_service;

    g_return_val_if_fail(conv != NULL, unknown_service);

    if(is_twitter_conv(conv))
        service = twitter_service;
    else if(is_wassr_conv(conv))
        service = wassr_service;
    else if(is_identica_conv(conv))
        service = identica_service;
    else if(is_jisko_conv(conv))
        service = jisko_service;
    else if(is_ffeed_conv(conv))
        service = ffeed_service;

    return service;
}

gboolean
pt_uri_handler(const char *proto, const char *cmd, GHashTable *params)
{
    char *idstr = NULL;
	const char *acct_id = NULL;
	PurpleConversation *conv = NULL;
	PidginConversation *gtkconv = NULL;
    guint64 msgid = 0;
    gchar *sender = NULL, *recipient = NULL, *msg = NULL;

    if(g_ascii_strcasecmp(proto, "pt"))
       return FALSE;

    twitter_debug("params=%p\n", params);

    acct_id = purple_prefs_get_string(OPT_SCREEN_NAME_TWITTER);
    twitter_debug("acct_id=%s\n", acct_id);

    if(strstr(cmd, "reply-twitter")) {
        sender = g_hash_table_lookup(params, "user");
        idstr = g_hash_table_lookup(params, "id");
        if(idstr)
            msgid = strtoull(idstr, NULL, 10);

        /* find conv */
        conv = purple_find_conversation_with_account(
            PURPLE_CONV_TYPE_ANY, "[email protected]",
            account_for_twitter); /* xxx */
        twitter_debug("conv = %p\n", conv);
        gtkconv = PIDGIN_CONVERSATION(conv);

        twitter_debug("sender = %s, id = %llu\n", sender, (unsigned long long)msgid);

        recipient = g_strdup_printf("@%s ", sender);
        gtk_text_buffer_insert_at_cursor(gtkconv->entry_buffer,
                                         recipient, -1);

        gtk_widget_grab_focus(GTK_WIDGET(gtkconv->entry));
        g_free(recipient);
        reply_to_msgid = msgid; /* xxx */

        return TRUE;
    }
    else if(strstr(cmd, "fav-twitter")) {
        idstr = g_hash_table_lookup(params, "id");
        fav_with_api(strtoull(idstr, NULL, 10));
        return TRUE;
    }
    else if(strstr(cmd, "retweet-twitter")) {
        gchar *msg0;
        sender = g_hash_table_lookup(params, "user");
        idstr = g_hash_table_lookup(params, "id");
        msg0 = g_hash_table_lookup(params, "msg");
        msg = g_uri_unescape_string(msg0, NULL);

        if(idstr)
            msgid = strtoull(idstr, NULL, 10);

        /* find conv */
        conv = purple_find_conversation_with_account(
            PURPLE_CONV_TYPE_ANY, "[email protected]",
            account_for_twitter); /* xxx */
        twitter_debug("conv = %p\n", conv);
        gtkconv = PIDGIN_CONVERSATION(conv);

        twitter_debug("sender = %s, id = %llu\n", sender, (unsigned long long)msgid);

        recipient = g_strdup_printf("RT @%s: %s", sender, msg);
        g_free(msg);
        gtk_text_buffer_insert_at_cursor(gtkconv->entry_buffer,
                                         recipient, -1);

        GtkTextIter iter;
        gtk_text_buffer_get_start_iter(gtkconv->entry_buffer, &iter);
        gtk_text_buffer_place_cursor(gtkconv->entry_buffer, &iter);

        gtk_widget_grab_focus(GTK_WIDGET(gtkconv->entry));
        g_free(recipient);

        return TRUE;
    }
    return FALSE;
}

gchar *
twitter_make_link_string(gchar **str)
{
    GMatchInfo *match_info = NULL;
    gchar *boddy0 = NULL, *boddy = NULL;
    gchar *newstr = NULL, *linkstr = NULL;
    gchar *match = NULL;
    gchar *idstr = NULL, *user = NULL;

    twitter_debug("called\n");

    /* buffer without ptmsgid=123 */
    boddy0 = g_regex_replace(regp[SENDER], *str, -1, 0, "", 0, NULL);
    boddy = g_regex_replace(regp[MESSAGE_ID], boddy0, -1, 0, "", 0, NULL);
    g_free(boddy0);
    boddy0 = NULL;
    twitter_debug("boddy = %s\n", boddy);

    boddy0 = g_uri_escape_string(boddy, " !$()*,;:@/?#[]", TRUE);
    g_free(boddy);
    boddy = boddy0;

    /* sender */
    g_regex_match(regp[SENDER], *str, 0, &match_info);
    if(g_match_info_matches(match_info)) {
        user = g_match_info_fetch(match_info, 2);
        twitter_debug("user = %s\n", user);
        g_match_info_free(match_info);
        match_info = NULL;
    }

    /* link string */
    g_regex_match(regp[MESSAGE_ID], *str, 0, &match_info);
    if(match_info) {
        match = g_match_info_fetch(match_info, 1);
        idstr = match ? match : "0";
        linkstr = g_strdup_printf(LINK_FORMAT_TWITTER,
                                  idstr, user,         /* Reply */
                                  idstr,               /* Favorite */
                                  idstr, user, boddy); /* Retweet */

        twitter_debug("linkstr = %s\n", linkstr);

        newstr = g_regex_replace(regp[MESSAGE_ID], *str, -1, 0,
                                 "",
                                 0, NULL);

        twitter_debug("newstr = %s\n", newstr);

        g_free(*str);
        *str = newstr;

        g_free(match);
        match = NULL;

        g_match_info_free(match_info);
        match_info = NULL;
    }

    g_free(user);
    g_free(boddy);

    return linkstr;
}