Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --- a/libpurple/protocols/jabber/Makefile.am
- +++ b/libpurple/protocols/jabber/Makefile.am
- @@ -65,6 +65,8 @@
- jingle/transport.h \
- jutil.c \
- jutil.h \
- + mam.c \
- + mam.h \
- message.c \
- message.h \
- namespaces.h \
- --- a/libpurple/protocols/jabber/Makefile.mingw
- +++ b/libpurple/protocols/jabber/Makefile.mingw
- @@ -74,6 +74,7 @@
- jingle/session.c \
- jingle/transport.c \
- jutil.c \
- + mam.c \
- message.c \
- oob.c \
- parser.c \
- --- a/libpurple/protocols/jabber/disco.c
- +++ b/libpurple/protocols/jabber/disco.c
- @@ -36,6 +36,7 @@
- #include "iq.h"
- #include "jabber.h"
- #include "jingle/jingle.h"
- +#include "mam.h"
- #include "pep.h"
- #include "presence.h"
- #include "roster.h"
- @@ -295,13 +296,16 @@
- capabilities |= JABBER_CAP_PING;
- else if(!strcmp(var, NS_DISCO_ITEMS))
- capabilities |= JABBER_CAP_ITEMS;
- - else if(!strcmp(var, "http://jabber.org/protocol/commands")) {
- + else if(!strcmp(var, "http://jabber.org/protocol/commands"))
- capabilities |= JABBER_CAP_ADHOC;
- - }
- else if(!strcmp(var, NS_IBB)) {
- purple_debug_info("jabber", "remote supports IBB\n");
- capabilities |= JABBER_CAP_IBB;
- }
- + else if(!strcmp(var, NS_XMPP_CARBONS))
- + capabilities |= JABBER_CAP_CARBONS;
- + else if(!strcmp(var, NS_XMPP_MAM))
- + capabilities |= JABBER_CAP_MAM;
- }
- }
- @@ -386,6 +390,29 @@
- jabber_request_block_list(js);
- }
- + if ((js->server_caps & JABBER_CAP_CARBONS) && purple_account_get_bool(js->gc->account, "carbons", FALSE)) {
- + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
- + xmlnode *enable = xmlnode_new_child(iq->node, "enable");
- +
- + purple_debug_info("jabber", "Automatically enabling Carbons.\n");
- +
- + xmlnode_set_namespace(enable, NS_XMPP_CARBONS);
- +
- + jabber_iq_send(iq);
- + }
- +
- + if ((js->server_caps & JABBER_CAP_MAM) && purple_account_get_bool(js->gc->account, "mam", FALSE)) {
- + purple_debug_info("jabber", "MAM Requesting.\n");
- +
- + time_t mam_laststamp = (time_t *)purple_account_get_int(js->gc->account, "mam_laststamp", time(0));
- + purple_account_set_int(js->gc->account, "mam_laststamp", mam_laststamp + 1);
- +
- + const struct tm *unixtime = gmtime(&mam_laststamp);
- + strcpy(js->mam->last_timestamp, purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", unixtime));
- +
- + jabber_mam_add_to_queue(js, js->mam->last_timestamp, NULL, NULL);
- + }
- +
- /* If there are manually specified bytestream proxies, query them */
- ft_proxies = purple_account_get_string(js->gc->account, "ft_proxies", NULL);
- if (ft_proxies) {
- @@ -574,6 +601,10 @@
- js->server_caps |= JABBER_CAP_ADHOC;
- } else if (!strcmp(NS_SIMPLE_BLOCKING, var)) {
- js->server_caps |= JABBER_CAP_BLOCKING;
- + } else if(!strcmp(var, NS_XMPP_CARBONS)) {
- + js->server_caps |= JABBER_CAP_CARBONS;
- + } else if(!strcmp(var, NS_XMPP_MAM)) {
- + js->server_caps |= JABBER_CAP_MAM;
- }
- }
- --- a/libpurple/protocols/jabber/jabber.c
- +++ b/libpurple/protocols/jabber/jabber.c
- @@ -933,6 +933,7 @@
- js = gc->proto_data = g_new0(JabberStream, 1);
- js->gc = gc;
- js->fd = -1;
- + js->mam = calloc(1, sizeof(mam_t));
- if (g_strcmp0("prpl-facebook-xmpp",
- purple_account_get_protocol_id(account)) == 0)
- @@ -1731,6 +1732,10 @@
- js->google_relay_requests);
- }
- }
- +
- + jabber_mam_clear(js->mam);
- + free(js->mam);
- + js->mam = NULL;
- g_free(js);
- @@ -2574,6 +2579,8 @@
- JabberStream *js = gc->proto_data;
- GList *m = NULL;
- PurplePluginAction *act;
- + gboolean has_carbons = purple_account_get_bool(gc->account, "carbons", FALSE);
- + gboolean has_mam = purple_account_get_bool(gc->account, "mam", FALSE);
- act = purple_plugin_action_new(_("Set User Info..."),
- jabber_setup_set_info);
- @@ -2597,6 +2604,16 @@
- if(js->commands)
- jabber_adhoc_init_server_commands(js, &m);
- + if(js->server_caps & JABBER_CAP_CARBONS) {
- + act = purple_plugin_action_new((has_carbons ? _("Disable Message Copies") : _("Enable Message Copies")), jabber_toggle_carbons);
- + m = g_list_append(m, act);
- + }
- +
- + if(js->server_caps & JABBER_CAP_MAM) {
- + act = purple_plugin_action_new((has_mam ? _("Disable Messaging Archive Management") : _("Enable Messaging Archive Management")), jabber_toggle_mam);
- + m = g_list_append(m, act);
- + }
- +
- return m;
- }
- --- a/libpurple/protocols/jabber/jabber.h
- +++ b/libpurple/protocols/jabber/jabber.h
- @@ -48,9 +48,12 @@
- JABBER_CAP_ITEMS = 1 << 14,
- JABBER_CAP_ROSTER_VERSIONING = 1 << 15,
- -
- +
- JABBER_CAP_FACEBOOK = 1 << 16,
- + JABBER_CAP_CARBONS = 1 << 17,
- + JABBER_CAP_MAM = 1 << 18,
- +
- JABBER_CAP_RETRIEVED = 1 << 31
- } JabberCapabilities;
- @@ -62,6 +65,7 @@
- #include "connection.h"
- #include "dnsquery.h"
- #include "dnssrv.h"
- +#include "mam.h"
- #include "media.h"
- #include "mediamanager.h"
- #include "roomlist.h"
- @@ -287,6 +291,8 @@
- /* facebook quirks */
- gboolean facebook_roster_cleanup_performed;
- +
- + mam_t *mam;
- };
- typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *namespace);
- --- /dev/null
- +++ b/libpurple/protocols/jabber/mam.c
- @@ -0,0 +1,245 @@
- +/*
- + * purple - Jabber Protocol Plugin
- + *
- + * Purple is the legal property of its developers, whose names are too numerous
- + * to list here. Please refer to the COPYRIGHT file distributed with this
- + * source distribution.
- + *
- + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- + *
- + */
- +
- +#include "internal.h"
- +#include "request.h"
- +
- +#include "jabber.h"
- +#include "mam.h"
- +
- +struct list_s
- +{
- + void *data;
- + list_t *prev;
- + list_t *next;
- +};
- +
- +list_t * list_append(list_t *li, void *data)
- +{
- + list_t *nli = malloc(sizeof(list_t));
- + nli->data = data;
- + if(!li) {
- + nli->prev = nli->next = NULL;
- + } else {
- + nli->prev = li;
- + nli->next = li->next;
- + if(li->next)
- + li->next->prev = nli;
- + li->next = nli;
- + }
- + return nli;
- +}
- +
- +list_t * list_insert(list_t *li, void *data)
- +{
- + list_t *nli = malloc(sizeof(list_t));
- + nli->data = data;
- + if(!li) {
- + nli->prev = nli->next = NULL;
- + } else {
- + nli->next = li;
- + nli->prev = li->prev;
- + if(li->prev)
- + li->prev->next = nli;
- + li->prev = nli;
- + }
- + return nli;
- +}
- +
- +list_t * list_delete(list_t *li, void *data)
- +{
- + if(!li)
- + return NULL;
- +
- + list_t *i = li;
- + if(data) {
- + i = list_get_first(li);
- + while(i) {
- + if(data == list_get_data(i))
- + break;
- + i = i->next;
- + }
- + if(!i)
- + return li;
- + }
- +
- + list_t *r = NULL;
- + if(i->next) {
- + i->next->prev = i->prev;
- + r = i->next;
- + }
- + if(i->prev) {
- + i->prev->next = i->next;
- + r = i->prev;
- + }
- + free(i);
- + return r;
- +}
- +
- +inline list_t * list_get_first(list_t *li)
- +{
- + if(!li)
- + return NULL;
- + while(li->prev)
- + li = li->prev;
- + return li;
- +}
- +
- +inline list_t * list_get_next(list_t *li)
- +{
- + return li->next;
- +}
- +
- +inline void * list_get_data(list_t *li)
- +{
- + return li->data;
- +}
- +
- +void jabber_mam_clear(mam_t *mam)
- +{
- + if (mam)
- + return;
- +
- + list_t *queue_item = list_get_first(mam->queue);
- + while (queue_item) {
- + mam_item_t *mam_item = list_get_data(queue_item);
- +
- + free(mam_item->start);
- + free(mam_item->end);
- + free(mam_item->with);
- + free(mam_item);
- +
- + queue_item = list_get_next(queue_item);
- + }
- +}
- +
- +void jabber_mam_add_to_queue(JabberStream *js, const char* start, const char* end, const char* with)
- +{
- + if (!js->mam)
- + return;
- +
- + mam_item_t *mam_item = calloc(1, sizeof(mam_item_t));
- +
- + if (start) {
- + mam_item->start = calloc(1, strlen(start) + 1);
- + strcpy(mam_item->start, start);
- + }
- +
- + if (end) {
- + mam_item->end = calloc(1, strlen(end) + 1);
- + strcpy(mam_item->end, end);
- + }
- +
- + if (with) {
- + mam_item->with = calloc(1, strlen(with) + 1);
- + strcpy(mam_item->with, with);
- + }
- +
- + js->mam->queue = list_append(js->mam->queue, mam_item);
- +
- + jabber_mam_process(js, NULL);
- +}
- +
- +void jabber_mam_process(JabberStream *js, const char* after)
- +{
- + if (!js->mam)
- + return;
- +
- + if (js->mam->current && js->mam->current->completed) {
- + free(js->mam->current->start);
- + free(js->mam->current->end);
- + free(js->mam->current->with);
- +
- + memset(js->mam->last_timestamp, 0, 32);
- +
- + free(js->mam->current);
- + js->mam->current = NULL;
- + }
- +
- + if (!js->mam->current) {
- + list_t *queue_item = list_get_first(js->mam->queue);
- + if (queue_item) {
- + js->mam->queue = list_delete(js->mam->queue, queue_item);
- +
- + js->mam->current = list_get_data(queue_item);
- +
- + js->mam->queue = list_get_next(js->mam->queue);
- + }
- + }
- +
- + if (js->mam->current)
- + jabber_mam_request(js, after);
- +}
- +
- +void jabber_mam_request(JabberStream *js, const char* after)
- +{
- + if (!js->mam)
- + return;
- +
- + JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_SET, NS_XMPP_MAM);
- + xmlnode *query = xmlnode_get_child(iq->node, "query");
- +
- + xmlnode *x = xmlnode_new_child(query, "x");
- + xmlnode_set_namespace(x, "jabber:x:data");
- +
- + xmlnode *field = xmlnode_new_child(x, "field");
- + xmlnode_set_attrib(field, "type", "hidden");
- + xmlnode_set_attrib(field, "var", "FORM_TYPE");
- + xmlnode *value = xmlnode_new_child(field, "value");
- + xmlnode_insert_data(value, NS_XMPP_MAM, -1);
- +
- + if (after) {
- + xmlnode *set = xmlnode_new_child(query, "set");
- + xmlnode_set_namespace(set, NS_RSM);
- +
- + value = xmlnode_new_child(set, "after");
- + xmlnode_insert_data(value, after, -1);
- + }
- +
- + if (js->mam->current->start) {
- + field = xmlnode_new_child(x, "field");
- + xmlnode_set_attrib(field, "var", "start");
- +
- + value = xmlnode_new_child(field, "value");
- + xmlnode_insert_data(value, js->mam->current->start, -1);
- + }
- +
- + if (js->mam->current->end) {
- + field = xmlnode_new_child(x, "field");
- + xmlnode_set_attrib(field, "var", "end");
- +
- + value = xmlnode_new_child(field, "value");
- + xmlnode_insert_data(value, js->mam->current->end, -1);
- + }
- +
- + if (js->mam->current->with) {
- + field = xmlnode_new_child(x, "field");
- + xmlnode_set_attrib(field, "var", "with");
- +
- + value = xmlnode_new_child(field, "value");
- + xmlnode_insert_data(value, js->mam->current->with, -1);
- + }
- +
- + jabber_iq_send(iq);
- +}
- +
- --- /dev/null
- +++ b/libpurple/protocols/jabber/mam.h
- @@ -0,0 +1,56 @@
- +/*
- + * purple - Jabber Protocol Plugin
- + *
- + * Purple is the legal property of its developers, whose names are too numerous
- + * to list here. Please refer to the COPYRIGHT file distributed with this
- + * source distribution.
- + *
- + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- + *
- + */
- +
- +#ifndef PURPLE_JABBER_MAM_H_
- +#define PURPLE_JABBER_MAM_H_
- +
- +#include "xmlnode.h"
- +
- +typedef struct list_s list_t;
- +
- +list_t * list_append(list_t *, void *);
- +list_t * list_insert(list_t *, void *);
- +list_t * list_delete(list_t *, void *);
- +list_t * list_get_first(list_t *);
- +list_t * list_get_next(list_t *);
- +void * list_get_data(list_t *);
- +
- +typedef struct {
- + char *start;
- + char *end;
- + char *with;
- + gboolean completed;
- +} mam_item_t;
- +
- +typedef struct {
- + list_t *queue;
- + mam_item_t *current;
- + char last_timestamp[32];
- +} mam_t;
- +
- +void jabber_mam_clear(mam_t *mam);
- +void jabber_mam_add_to_queue(JabberStream *js, const char* start, const char* end, const char* with);
- +void jabber_mam_process(JabberStream *js, const char* after);
- +void jabber_mam_request(JabberStream *js, const char* after);
- +
- +#endif /* PURPLE_JABBER_MAM_H_ */
- --- a/libpurple/protocols/jabber/message.c
- +++ b/libpurple/protocols/jabber/message.c
- @@ -31,6 +31,7 @@
- #include "chat.h"
- #include "data.h"
- #include "google/google.h"
- +#include "mam.h"
- #include "message.h"
- #include "xmlnode.h"
- #include "pep.h"
- @@ -58,7 +59,8 @@
- static void handle_chat(JabberMessage *jm)
- {
- - JabberID *jid = jabber_id_new(jm->from);
- + gchar *contact = jm->outgoing ? jm->to : jm->from;
- + JabberID *jid = jabber_id_new(contact);
- PurpleConnection *gc;
- PurpleAccount *account;
- @@ -71,48 +73,50 @@
- gc = jm->js->gc;
- account = purple_connection_get_account(gc);
- - jb = jabber_buddy_find(jm->js, jm->from, TRUE);
- + jb = jabber_buddy_find(jm->js, contact, TRUE);
- jbr = jabber_buddy_find_resource(jb, jid->resource);
- if(!jm->xhtml && !jm->body) {
- - if (jbr && jm->chat_state != JM_STATE_NONE)
- - jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
- -
- - if(JM_STATE_COMPOSING == jm->chat_state) {
- - serv_got_typing(gc, jm->from, 0, PURPLE_TYPING);
- - } else if(JM_STATE_PAUSED == jm->chat_state) {
- - serv_got_typing(gc, jm->from, 0, PURPLE_TYPED);
- - } else if(JM_STATE_GONE == jm->chat_state) {
- - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
- - jm->from, account);
- - if (conv && jid->node && jid->domain) {
- - char buf[256];
- - PurpleBuddy *buddy;
- -
- - g_snprintf(buf, sizeof(buf), "%s@%s", jid->node, jid->domain);
- -
- - if ((buddy = purple_find_buddy(account, buf))) {
- - const char *who;
- - char *escaped;
- -
- - who = purple_buddy_get_alias(buddy);
- - escaped = g_markup_escape_text(who, -1);
- -
- - g_snprintf(buf, sizeof(buf),
- - _("%s has left the conversation."), escaped);
- - g_free(escaped);
- -
- - /* At some point when we restructure PurpleConversation,
- - * this should be able to be implemented by removing the
- - * user from the conversation like we do with chats now. */
- - purple_conversation_write(conv, "", buf,
- - PURPLE_MESSAGE_SYSTEM, time(NULL));
- + if (!jm->outgoing) {
- + if (jbr && jm->chat_state != JM_STATE_NONE)
- + jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
- +
- + if(JM_STATE_COMPOSING == jm->chat_state) {
- + serv_got_typing(gc, contact, 0, PURPLE_TYPING);
- + } else if(JM_STATE_PAUSED == jm->chat_state) {
- + serv_got_typing(gc, contact, 0, PURPLE_TYPED);
- + } else if(JM_STATE_GONE == jm->chat_state) {
- + PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
- + contact, account);
- + if (conv && jid->node && jid->domain) {
- + char buf[256];
- + PurpleBuddy *buddy;
- +
- + g_snprintf(buf, sizeof(buf), "%s@%s", jid->node, jid->domain);
- +
- + if ((buddy = purple_find_buddy(account, buf))) {
- + const char *who;
- + char *escaped;
- +
- + who = purple_buddy_get_alias(buddy);
- + escaped = g_markup_escape_text(who, -1);
- +
- + g_snprintf(buf, sizeof(buf),
- + _("%s has left the conversation."), escaped);
- + g_free(escaped);
- +
- + /* At some point when we restructure PurpleConversation,
- + * this should be able to be implemented by removing the
- + * user from the conversation like we do with chats now. */
- + purple_conversation_write(conv, "", buf,
- + PURPLE_MESSAGE_SYSTEM, time(NULL));
- + }
- }
- - }
- - serv_got_typing_stopped(gc, jm->from);
- + serv_got_typing_stopped(gc, contact);
- - } else {
- - serv_got_typing_stopped(gc, jm->from);
- + } else {
- + serv_got_typing_stopped(gc, contact);
- + }
- }
- } else {
- if (jid->resource) {
- @@ -128,12 +132,12 @@
- PurpleConversation *conv;
- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
- - jm->from, account);
- - if (conv && !g_str_equal(jm->from,
- + contact, account);
- + if (conv && !g_str_equal(contact,
- purple_conversation_get_name(conv))) {
- purple_debug_info("jabber", "Binding conversation to %s\n",
- - jm->from);
- - purple_conversation_set_name(conv, jm->from);
- + contact);
- + purple_conversation_set_name(conv, contact);
- }
- }
- @@ -156,7 +160,8 @@
- jm->body = jabber_google_format_to_html(jm->body);
- g_free(tmp);
- }
- - serv_got_im(gc, jm->from, jm->xhtml ? jm->xhtml : jm->body, 0, jm->sent);
- + serv_got_im(gc, contact, jm->xhtml ? jm->xhtml : jm->body,
- + (jm->outgoing ? PURPLE_MESSAGE_SEND : PURPLE_MESSAGE_RECV), jm->sent);
- }
- jabber_id_free(jid);
- @@ -502,7 +507,88 @@
- JabberMessage *jm;
- const char *id, *from, *to, *type;
- xmlnode *child;
- - gboolean signal_return;
- + gboolean signal_return, is_outgoing = FALSE;
- + time_t message_timestamp = time(NULL);
- + gboolean delayed = FALSE;
- +
- + /* Check if this is a carbon-copy of a message.
- + * If so, use that instead for the rest of this function,
- + * but keep track of wether the from and to should be swapped.
- + */
- + from = xmlnode_get_attrib(packet, "from");
- +
- + if (jabber_is_own_account(js, from)) {
- + xmlnode *received = xmlnode_get_child_with_namespace(packet, "received", NS_XMPP_CARBONS);
- + xmlnode *sent = xmlnode_get_child_with_namespace(packet, "sent", NS_XMPP_CARBONS);
- + xmlnode *result = xmlnode_get_child_with_namespace(packet, "result", NS_XMPP_MAM);
- + xmlnode *fin = xmlnode_get_child_with_namespace(packet, "fin", NS_XMPP_MAM);
- +
- + if (received || sent || result) {
- + xmlnode *forwarded = xmlnode_get_child_with_namespace(received ? received : sent ? sent : result, "forwarded", NS_XMPP_FORWARD);
- +
- + if (forwarded) {
- + xmlnode *message = xmlnode_get_child_with_namespace(forwarded, "message", NS_XMPP_CLIENT);
- + xmlnode *delay = xmlnode_get_child_with_namespace(forwarded, "delay", NS_DELAYED_DELIVERY);
- +
- + if (message) {
- + purple_debug_info("jabber", "It's forwarded message, using the wrapped message instead.\n");
- + packet = message;
- +
- + from = xmlnode_get_attrib(packet, "from");
- +
- + if (result) {
- + JabberID *jid = jabber_id_new(from);
- +
- + if (!jid)
- + return;
- +
- + gboolean equal = (purple_strequal(jid->node, js->user->node) &&
- + g_str_equal(jid->domain, js->user->domain));
- +
- + if (equal)
- + is_outgoing = TRUE;
- +
- + jabber_id_free(jid);
- + }
- + else if (sent)
- + is_outgoing = TRUE;
- +
- + if (delay) {
- + const char *timestamp = xmlnode_get_attrib(delay, "stamp");
- +
- + if(timestamp) {
- + if (result) {
- + memset(js->mam->last_timestamp, 0, 32);
- + strcpy(js->mam->last_timestamp, timestamp);
- + }
- +
- + purple_debug_info("jabber", "Found a delay stamp: %s\n", timestamp);
- +
- + delayed = TRUE;
- +
- + message_timestamp = purple_str_to_time(timestamp, TRUE, NULL, NULL, NULL);
- + }
- + }
- + }
- + }
- + } else if (fin) {
- + gboolean complete = xmlnode_get_attrib(fin, "complete") ? TRUE : FALSE;
- + if (complete) {
- + js->mam->current->completed = TRUE;
- +
- + jabber_mam_process(js, NULL);
- + } else {
- + xmlnode *set = xmlnode_get_child_with_namespace(fin, "set", NS_RSM);
- + if (set) {
- + xmlnode *last = xmlnode_get_child(set, "last");
- + if (last) {
- + jabber_mam_process(js, xmlnode_get_data(last));
- + }
- + }
- + }
- + return;
- + }
- + }
- from = xmlnode_get_attrib(packet, "from");
- id = xmlnode_get_attrib(packet, "id");
- @@ -516,9 +602,13 @@
- jm = g_new0(JabberMessage, 1);
- jm->js = js;
- - jm->sent = time(NULL);
- - jm->delayed = FALSE;
- + jm->sent = message_timestamp;
- + jm->delayed = delayed;
- jm->chat_state = JM_STATE_NONE;
- + jm->outgoing = is_outgoing;
- +
- + if (jm->sent > purple_account_get_int(js->gc->account, "mam_laststamp", 0))
- + purple_account_set_int(js->gc->account, "mam_laststamp", jm->sent);
- if(type) {
- if(!strcmp(type, "normal"))
- @@ -624,12 +714,12 @@
- jm->type == JABBER_MESSAGE_CHAT) {
- conv =
- purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
- - from, account);
- + is_outgoing ? to : from, account);
- if (!conv) {
- /* we need to create the conversation here */
- conv =
- purple_conversation_new(PURPLE_CONV_TYPE_IM,
- - account, from);
- + account, is_outgoing ? to : from);
- }
- }
- }
- @@ -709,6 +799,7 @@
- } else if(!strcmp(child->name, "attention") && !strcmp(xmlns, NS_ATTENTION)) {
- jm->hasBuzz = TRUE;
- } else if(!strcmp(child->name, "delay") && !strcmp(xmlns, NS_DELAYED_DELIVERY)) {
- + /* Carbons/Stanza fowarding might have already set jm->delayed. However, this timestamp was certainly applied earlier, so it overrides Carbons. */
- const char *timestamp = xmlnode_get_attrib(child, "stamp");
- jm->delayed = TRUE;
- if(timestamp)
- @@ -1085,6 +1176,8 @@
- }
- }
- + purple_account_set_int(jm->js->gc->account, "mam_laststamp", time(0));
- +
- jabber_send(jm->js, message);
- xmlnode_free(message);
- @@ -1305,3 +1398,48 @@
- return purple_account_get_bool(account, "custom_smileys", TRUE);
- }
- +
- +void jabber_toggle_carbons(PurplePluginAction *action) {
- + PurpleConnection *gc = (PurpleConnection *) action->context;
- + JabberStream *js = purple_connection_get_protocol_data(gc);
- + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
- + gboolean has_carbons = !purple_account_get_bool(purple_connection_get_account(gc), "carbons", FALSE);
- + xmlnode *node;
- +
- + if (has_carbons) {
- + node = xmlnode_new_child(iq->node, "enable");
- + } else {
- + node = xmlnode_new_child(iq->node, "disable");
- + }
- +
- + purple_account_set_bool(gc->account, "carbons", has_carbons);
- +
- + xmlnode_set_namespace(node, NS_XMPP_CARBONS);
- + jabber_iq_send(iq);
- +
- + /* Force an update of the account actions. */
- + purple_prpl_got_account_actions(purple_connection_get_account(gc));
- +}
- +
- +void jabber_toggle_mam(PurplePluginAction *action) {
- + PurpleConnection *gc = (PurpleConnection *) action->context;
- + JabberStream *js = purple_connection_get_protocol_data(gc);
- + gboolean has_mam = !purple_account_get_bool(purple_connection_get_account(gc), "mam", FALSE);
- +
- + purple_account_set_bool(gc->account, "mam", has_mam);
- +
- + if (has_mam) {
- + purple_debug_info("jabber", "MAM Requesting.\n");
- +
- + time_t mam_laststamp = (time_t *)purple_account_get_int(js->gc->account, "mam_laststamp", time(0));
- + purple_account_set_int(js->gc->account, "mam_laststamp", mam_laststamp);
- +
- + const struct tm *unixtime = gmtime(&mam_laststamp);
- + strcpy(js->mam->last_timestamp, purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", unixtime));
- +
- + jabber_mam_add_to_queue(js, js->mam->last_timestamp, NULL, NULL);
- + }
- +
- + /* Force an update of the account actions. */
- + purple_prpl_got_account_actions(purple_connection_get_account(gc));
- +}
- --- a/libpurple/protocols/jabber/message.h
- +++ b/libpurple/protocols/jabber/message.h
- @@ -62,6 +62,7 @@
- } chat_state;
- GList *etc;
- GList *eventitems;
- + gboolean outgoing;
- } JabberMessage;
- void jabber_message_free(JabberMessage *jm);
- @@ -79,4 +80,7 @@
- gboolean jabber_custom_smileys_isenabled(JabberStream *js, const const gchar *namespace);
- +void jabber_toggle_carbons(PurplePluginAction *action);
- +void jabber_toggle_mam(PurplePluginAction *action);
- +
- #endif /* PURPLE_JABBER_MESSAGE_H_ */
- --- a/libpurple/protocols/jabber/namespaces.h
- +++ b/libpurple/protocols/jabber/namespaces.h
- @@ -42,6 +42,9 @@
- /* XEP-0047 IBB (In-band bytestreams) */
- #define NS_IBB "http://jabber.org/protocol/ibb"
- +/* XEP-0059 Result Set Management (RSM) */
- +#define NS_RSM "http://jabber.org/protocol/rsm"
- +
- /* XEP-0065 SOCKS5 Bytestreams */
- #define NS_BYTESTREAMS "http://jabber.org/protocol/bytestreams"
- @@ -95,6 +98,15 @@
- /* XEP-0264 File Transfer Thumbnails (Thumbs) */
- #define NS_THUMBS "urn:xmpp:thumbs:0"
- +/* XEP-0280 Message Carbons */
- +#define NS_XMPP_CARBONS "urn:xmpp:carbons:2"
- +
- +/* XEP-0297 Message Forwarding */
- +#define NS_XMPP_FORWARD "urn:xmpp:forward:0"
- +
- +/* XEP-0313 Message Archive Management */
- +#define NS_XMPP_MAM "urn:xmpp:mam:0"
- +
- /* Google extensions */
- #define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
- #define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
- --- a/libpurple/server.c
- +++ b/libpurple/server.c
- @@ -575,11 +575,6 @@
- mtime = time(NULL);
- }
- - /*
- - * XXX: Should we be setting this here, or relying on prpls to set it?
- - */
- - flags |= PURPLE_MESSAGE_RECV;
- -
- if (!purple_privacy_check(account, who)) {
- purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
- account, who, msg, flags, (unsigned int)mtime);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement