diff --git a/purple/purplexpcom/public/Makefile.in b/purple/purplexpcom/public/Makefile.in --- a/purple/purplexpcom/public/Makefile.in +++ b/purple/purplexpcom/public/Makefile.in @@ -53,15 +53,16 @@ XPIDLSRCS = \ purpleIMessage.idl \ purpleIPlugin.idl \ purpleIPref.idl \ purpleIProtocol.idl \ purpleIProxy.idl \ purpleISocket.idl \ purpleITag.idl \ purpleITooltipInfo.idl \ + purpleIXMPPNode.idl \ $(NULL) ifeq ($(OS_ARCH),Darwin) XPIDLSRCS += nsIDockBadgeService.idl endif include $(topsrcdir)/config/rules.mk diff --git a/purple/purplexpcom/public/purpleIAccount.idl b/purple/purplexpcom/public/purpleIAccount.idl --- a/purple/purplexpcom/public/purpleIAccount.idl +++ b/purple/purplexpcom/public/purpleIAccount.idl @@ -87,16 +87,20 @@ interface purpleIAccount: nsISupports { nsISimpleEnumerator getChatRoomFields(); purpleIChatRoomFieldValues getChatRoomDefaultFieldValues([optional] in AUTF8String aDefaultChatName); /* * Create a new chat conversation if it doesn't already exist. * Returns the conversation if it already existed, null otherwise */ void joinChat(in purpleIChatRoomFieldValues aComponents); + /* Send raw data through the connexion, if supported by the + underlying protocol plugin. */ + void sendRawData([size_is(aLength)] in string aString, in PRUint32 aLength); + readonly attribute AUTF8String name; readonly attribute AUTF8String id; readonly attribute purpleIProtocol protocol; attribute boolean autoLogin; /* This is the value when the preference firstConnectionState is not set. It indicates that the account has already been successfully connected at diff --git a/purple/purplexpcom/public/purpleIXMPPNode.idl b/purple/purplexpcom/public/purpleIXMPPNode.idl new file mode 100644 --- /dev/null +++ b/purple/purplexpcom/public/purpleIXMPPNode.idl @@ -0,0 +1,57 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Instantbird messenging client, released + * 2009. + * + * The Initial Developer of the Original Code is + * Florian QUEZE . + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" +interface purpleIAccount; + +/* + * This is used to read XMPP stanza received by Jabber accounts before + * libpurple processes them. + */ +[scriptable, uuid(2de1b0a5-2bc9-4236-8231-a9ff5f853ffb)] +interface purpleIXMPPNode: nsISupports { + /* the raw XML string */ + AUTF8String toString(); + /* the pretty printed XML string */ + AUTF8String toPrettyString(); + + /* If set to true, libpurple will not process this XML node */ + attribute boolean handled; + + /* The account that received the stanza */ + readonly attribute purpleIAccount account; +}; diff --git a/purple/purplexpcom/src/purpleAccount.cpp b/purple/purplexpcom/src/purpleAccount.cpp --- a/purple/purplexpcom/src/purpleAccount.cpp +++ b/purple/purplexpcom/src/purpleAccount.cpp @@ -883,16 +883,38 @@ NS_IMETHODIMP purpleAccount::JoinChat(pu GHashTable *components; nsresult rv = aComponents->GetHashTable(&components); NS_ENSURE_SUCCESS(rv, rv); serv_join_chat(gc, components); return NS_OK; } +/* void sendRawData ([size_is (aLength)] in string aString, in PRUint32 aLength); */ +NS_IMETHODIMP purpleAccount::SendRawData(const char *aString, PRUint32 aLength) +{ + PURPLE_ENSURE_INIT(mProtocol); + + if (!mAccount) + return NS_ERROR_NOT_IMPLEMENTED; + + PurpleConnection *gc = purple_account_get_connection(mAccount); + NS_ENSURE_TRUE(gc, NS_ERROR_FAILURE); + + PurplePluginProtocolInfo *prplInfo; + nsresult rv = mProtocol->GetInfo(&prplInfo); + NS_ENSURE_SUCCESS(rv, rv); + + if (!prplInfo->send_raw) + return NS_ERROR_NOT_IMPLEMENTED; + + prplInfo->send_raw(gc, aString, aLength); + return NS_OK; +} + /* readonly attribute AUTF8String name; */ NS_IMETHODIMP purpleAccount::GetName(nsACString& aName) { PURPLE_ENSURE_INIT(INIT_CONDITION); if (NS_UNLIKELY(!mAccount)) { // Get the account name from the preferences nsresult rv = GetPrefBranch(); diff --git a/purple/purplexpcom/src/purpleInit.cpp b/purple/purplexpcom/src/purpleInit.cpp --- a/purple/purplexpcom/src/purpleInit.cpp +++ b/purple/purplexpcom/src/purpleInit.cpp @@ -52,16 +52,17 @@ #include #include #include #include #include #include #include #include +#include #include #pragma GCC visibility pop #include #ifndef _WIN32 #include #endif @@ -71,16 +72,17 @@ #include "purpleCoreService.h" #include "purpleGetText.h" #include "purpleMessage.h" #include "purpleTimer.h" #include "purpleSockets.h" #include "purpleDebug.h" #include "purpleDNS.h" #include +#include #include #include #include #include #include #include #include #include @@ -94,16 +96,18 @@ #include #include #include #include #include #include #include #include +#include +#include #define PURPLE_PROTOCOL_PLUGIN_CATEGORY "purple-protocol-plugin" #ifdef PR_LOGGING // // NSPR_LOG_MODULES=purpleInit:5 // @@ -524,16 +528,140 @@ static PurpleBlistUiOps blist_uiops = { NULL, /* set_visible */ NULL, /* request_add_buddy */ NULL, /* request_add_chat */ NULL, /* request_add_group */ NULL, NULL, NULL, NULL }; +/* Jabber specific signals */ +class purpleXMPPNode : public purpleIXMPPNode +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_PURPLEIXMPPNODE + + purpleXMPPNode(xmlnode *aNode, const PurpleConnection *gc) + : mNode(aNode), mHandled(PR_FALSE) { + PurpleAccount *pAccount = purple_connection_get_account(gc); + NS_ENSURE_TRUE(pAccount,); + mAccount = (purpleAccount *)pAccount->ui_data; + } + + PRBool GetHandled() { return mHandled; } + void Cleanup() { mNode = NULL; } + +private: + ~purpleXMPPNode() {} + +protected: + /* additional members */ + xmlnode *mNode; + PRBool mHandled; + nsCOMPtr mAccount; +}; + +NS_DECL_CLASSINFO(purpleXMPPNode) + +/* Implementation file */ +NS_IMPL_ISUPPORTS1_CI(purpleXMPPNode, purpleIXMPPNode) + +/* AUTF8String toString (); */ +NS_IMETHODIMP purpleXMPPNode::ToString(nsACString & aResult) +{ + NS_ENSURE_TRUE(mNode, NS_ERROR_UNEXPECTED); + + char *str = xmlnode_to_str(mNode, NULL); + aResult = str; + g_free(str); + return NS_OK; +} + +/* AUTF8String toPrettyString (); */ +NS_IMETHODIMP purpleXMPPNode::ToPrettyString(nsACString & aResult) +{ + NS_ENSURE_TRUE(mNode, NS_ERROR_UNEXPECTED); + + char *str = xmlnode_to_formatted_str(mNode, NULL); + aResult = str; + g_free(str); + return NS_OK; +} + +/* attribute boolean handled; */ +NS_IMETHODIMP purpleXMPPNode::GetHandled(PRBool *aHandled) +{ + *aHandled = mHandled; + return NS_OK; +} +NS_IMETHODIMP purpleXMPPNode::SetHandled(PRBool aHandled) +{ + mHandled = aHandled; + return NS_OK; +} + +/* readonly attribute purpleIAccount account; */ +NS_IMETHODIMP purpleXMPPNode::GetAccount(purpleIAccount * *aAccount) +{ + NS_ENSURE_TRUE(mAccount, NS_ERROR_NOT_INITIALIZED); + + NS_ADDREF(*aAccount = mAccount); + return NS_OK; +} + +static void jabber_stanza_received(PurpleConnection *gc, xmlnode **packet, gpointer null) +{ + nsCOMPtr XMPPNode = new purpleXMPPNode(*packet, gc); + + nsresult rv; + nsCOMPtr os = + do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, ); + + LOG(("Notifying observers of %s", "jabber-packet-received")); + rv = os->NotifyObservers(XMPPNode, "jabber-packet-received", nsnull); + NS_ENSURE_SUCCESS(rv, ); + + if (XMPPNode->GetHandled()) + *packet = NULL; + + XMPPNode->Cleanup(); +} + +static void jabber_stanza_sent(PurpleConnection *gc, char **packet, gpointer null) +{ + IMPL_GET_ACCOUNT; + + const nsCString cMsg(*packet); + nsString msg; + NS_CStringToUTF16(cMsg, NS_CSTRING_ENCODING_UTF8, msg); + + nsresult rv; + nsCOMPtr os = + do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, ); + + LOG(("Notifying observers of %s", "jabber-packet-sent")); + rv = os->NotifyObservers(account, "jabber-packet-sent", msg.get()); +} + +static void +connect_to_jabber_signals() +{ + int handle; + PurplePlugin *jabber = purple_find_prpl("prpl-jabber"); + if (!jabber) + return; + + purple_signal_connect(jabber, "jabber-receiving-xmlnode", &handle, + PURPLE_CALLBACK(jabber_stanza_received), NULL); + purple_signal_connect(jabber, "jabber-sending-text", &handle, + PURPLE_CALLBACK(jabber_stanza_sent), NULL); +} static void received_im_msg(PurpleAccount *account, char *sender, char *message, PurpleConversation *conv, PurpleMessageFlags flags) { LOG(("Received_im_msg")); nsCOMPtr os = do_GetService(NS_OBSERVERSERVICE_CONTRACTID); @@ -1140,16 +1268,17 @@ init_libpurple() /* Now, to connect the account(s), create a status and activate it. */ PurpleSavedStatus *status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE); purple_savedstatus_activate(status); connect_to_connections_signals(); connect_to_accounts_signals(); // connect_to_blist_signals(); connect_to_conversations_signals(); + connect_to_jabber_signals(); purple_cmd_register("say", "S", PURPLE_CMD_P_DEFAULT, (PurpleCmdFlag) (PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM), NULL, say_command_cb, "say <message>: Send a message normally as if you weren't using a command.", NULL); purple_cmd_register("away", "S", PURPLE_CMD_P_HIGH, (PurpleCmdFlag) (PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS),