view libpurple/gaim-url-handler @ 15787:b25acae693cd

Change connection.c:gaim_connection_error() to still work even if the message parameter is NULL. There's no reason to error-out of that function just because some yuppie didn't pass us an error message. But we still log a critical message, so those of you at home running with fatal_criticals will still crash. I noticed this because Jabber isn't handling <stream:error/> correctly right now. Anyone else notice this? The code is written to look for "stream:error", but our xmlnode stuff just sees "error" (even though the "stream:error" format is sent over the wire). I think it's because of the libxml change. To reproduce the problem, sign onto the same resource twice and note that the error message that Gaim gives you sucks.
author Mark Doliner <mark@kingant.net>
date Tue, 13 Mar 2007 07:33:08 +0000
parents 5fe8042783c1
children
line wrap: on
line source

#!/usr/bin/python

import dbus
import re
import sys
import time
import urllib

obj = dbus.SessionBus().get_object("net.sf.gaim.GaimService", "/net/sf/gaim/GaimObject")
gaim = dbus.Interface(obj, "net.sf.gaim.GaimInterface")

class CheckedObject:
    def __init__(self, obj):
        self.obj = obj

    def __getattr__(self, attr):
        return CheckedAttribute(self, attr)

class CheckedAttribute:
    def __init__(self, cobj, attr):
        self.cobj = cobj
        self.attr = attr

    def __call__(self, *args):
        result = self.cobj.obj.__getattr__(self.attr)(*args)
        if result == 0:
            raise "Error: " + self.attr + " " + str(args) + " returned " + str(result)
        return result

cgaim = CheckedObject(gaim)

def extendlist(list, length, fill):
    if len(list) < length:
        return list + [fill] * (length - len(list))
    else:
        return list

def convert(value):
    try:
        return int(value)
    except:
        return value

def findaccount(protocolname, accountname=""):
    try:
        # prefer connected accounts
        account = cgaim.GaimAccountsFindConnected(accountname, protocolname)
        return account
    except:
        # try to get any account and connect it
        account = cgaim.GaimAccountsFindAny(accountname, protocolname)
        gaim.GaimAccountSetStatusVargs(account, "online", 1)
        gaim.GaimAccountConnect(account)
        return account

def goim(account, screenname, message=None):
    # XXX: 1 == GAIM_CONV_TYPE_IM
    conversation = cgaim.GaimConversationNew(1, account, screenname)
    if message:
        gaim.GaimConvSendConfirm(conversation, message)

def gochat(account, params, message=None):
    connection = cgaim.GaimAccountGetConnection(account)
    gaim.ServJoinChat(connection, params)

    if message != None:
    	for i in range(20):
            # XXX: 2 == GAIM_CONV_TYPE_CHAT
            conversation = gaim.GaimFindConversationWithAccount(2, params.get("channel", params.get("room")), account)
            if conversation:
                gaim.GaimConvSendConfirm(conversation, message)
                break
            else:
                time.sleep(0.5)

def addbuddy(account, screenname, group="", alias=""):
    cgaim.GaimBlistRequestAddBuddy(account, screenname, group, alias)


def aim(uri):
    protocol = "prpl-oscar"
    match = re.match(r"^(aim|icq):([^?]*)(\?(.*))", uri)
    if not match:
        print "Invalid aim URI: %s" % uri
        return

    command = urllib.unquote_plus(match.group(2))
    paramstring = match.group(4)
    params = {}
    if paramstring:
        for param in paramstring.split("&"):
            key, value = extendlist(param.split("=", 1), 2, "")
            params[key] = urllib.unquote_plus(value)
    accountname = params.get("account", "")
    screenname = params.get("screenname", "")

    account = findaccount(protocol, accountname)

    if command.lower() == "goim":
        goim(account, screenname, params.get("message"))
    elif command.lower() == "gochat":
        gochat(account, params)
    elif command.lower() == "addbuddy":
        addbuddy(account, screenname, params.get("group", ""))

def gg(uri):
    protocol = "prpl-gg"
    match = re.match(r"^gg:(.*)", uri)
    if not match:
        print "Invalid gg URI: %s" % uri
        return

    screenname = urllib.unquote_plus(match.group(1))
    account = findaccount(protocol)
    goim(account, screenname)

def icq(uri):
    aim(uri)

def irc(uri):
    protocol = "prpl-irc"
    match = re.match(r"^irc:(//([^/]*)/)?([^?]*)(\?(.*))?", uri)
    if not match:
        print "Invalid irc URI: %s" % uri
        return

    server = urllib.unquote_plus(match.group(2)) or ""
    target = match.group(3) or ""
    query = match.group(5) or ""

    modifiers = {}
    if target:
        for modifier in target.split(",")[1:]:
            modifiers[modifier] = True

    isnick = modifiers.has_key("isnick")

    paramstring = match.group(5)
    params = {}
    if paramstring:
        for param in paramstring.split("&"):
            key, value = extendlist(param.split("=", 1), 2, "")
            params[key] = urllib.unquote_plus(value)

    account = findaccount(protocol)

    if (target != ""):
        if (isnick):
            goim(account, urllib.unquote_plus(target.split(",")[0]), params.get("msg"))
	else:
            channel = urllib.unquote_plus(target.split(",")[0])
            if channel[0] != "#":
                channel = "#" + channel
            gochat(account, {"server": server, "channel": channel, "password": params.get("key", "")}, params.get("msg"))

def msnim(uri):
    protocol = "prpl-msn"
    match = re.match(r"^msnim:([^?]*)(\?(.*))", uri)
    if not match:
        print "Invalid msnim URI: %s" % uri
        return

    command = urllib.unquote_plus(match.group(1))
    paramstring = match.group(3)
    params = {}
    if paramstring:
        for param in paramstring.split("&"):
            key, value = extendlist(param.split("=", 1), 2, "")
            params[key] = urllib.unquote_plus(value)
    screenname = params.get("contact", "")

    account = findaccount(protocol)

    if command.lower() == "chat":
        goim(account, screenname)
    elif command.lower() == "add":
        addbuddy(account, screenname)

def sip(uri):
    protocol = "prpl-simple"
    match = re.match(r"^sip:(.*)", uri)
    if not match:
        print "Invalid sip URI: %s" % uri
        return

    screenname = urllib.unquote_plus(match.group(1))
    account = findaccount(protocol)
    goim(account, screenname)

def xmpp(uri):
    protocol = "prpl-jabber"
    match = re.match(r"^xmpp:((//)?([^/?#]*))?(/?([^?#]*))(\?([^;#]*)(;([^#]*))?)?(#(.*))?", uri)
    if not match:
        print "Invalid xmpp URI: %s" % uri
        return

    tmp = match.group(3)
    if (tmp):
        accountname = urllib.unquote_plus(tmp)
    else:
        accountname = ""

    screenname = urllib.unquote_plus(match.group(5))

    tmp = match.group(7)
    if (tmp):
        command = urllib.unquote_plus(tmp)
    else:
        command = ""

    paramstring = match.group(9)
    params = {}
    if paramstring:
        for param in paramstring.split(";"):
            key, value = extendlist(param.split("=", 1), 2, "")
            params[key] = urllib.unquote_plus(value)

    account = findaccount(protocol, accountname)

    if command.lower() == "message":
        goim(account, screenname, params.get("body"))
    elif command.lower() == "join":
        room, server = screenname.split("@")
        gochat(account, {"room": room, "server": server})
    elif command.lower() == "roster":
        addbuddy(account, screenname, params.get("group", ""), params.get("name", ""))
    else:
        goim(account, screenname)

def ymsgr(uri):
    protocol = "prpl-yahoo"
    match = re.match(r"^ymsgr:([^?]*)(\?([^&]*)(&(.*))?)", uri)
    if not match:
        print "Invalid ymsgr URI: %s" % uri
        return

    command = urllib.unquote_plus(match.group(1))
    screenname = urllib.unquote_plus(match.group(3))
    paramstring = match.group(5)
    params = {}
    if paramstring:
        for param in paramstring.split("&"):
            key, value = extendlist(param.split("=", 1), 2, "")
            params[key] = urllib.unquote_plus(value)

    account = findaccount(protocol)

    if command.lower() == "sendim":
        goim(account, screenname, params.get("m"))
    elif command.lower() == "chat":
        gochat(account, {"room": screenname})
    elif command.lower() == "addfriend":
        addbuddy(account, screenname)


def main(argv=sys.argv):
    if len(argv) != 2:
        print "Usage: %s URI" % argv[0]
        print "Example: %s \"xmpp:romeo@montague.net?message\"" % argv[0]
        return

    uri = argv[1]
    type = uri.split(":")[0]

    if type == "aim":
        aim(uri)
    elif type == "gg":
        gg(uri)
    elif type == "icq":
        icq(uri)
    elif type == "irc":
        irc(uri)
    elif type == "msnim":
        msnim(uri)
    elif type == "sip":
        sip(uri)
    elif type == "xmpp":
        xmpp(uri)
    elif type == "ymsgr":
        ymsgr(uri)
    else:
        print "Unkown protocol: %s" % type

if __name__ == "__main__":
    main()