William Bowling is sharing code with you
Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.
Don't show this againadium / Plugins / Purple Service / AMPurpleJabberAdHocServer.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | #import "AMPurpleJabberAdHocServer.h"
#import "ESPurpleJabberAccount.h"
#import "AMPurpleJabberFormGenerator.h"
#import "AMPurpleJabberAdHocCommand.h"
#import <libpurple/jabber.h>
@interface AMPurpleJabberAdHocServer ()
- (BOOL)receivedCommand:(xmlnode*)command from:(NSString*)jid iqid:(NSString*)iqid;
- (void)addCommandsToXML:(xmlnode*)xml;
@end
@implementation AMPurpleJabberAdHocServer
static void AMPurpleJabberAdHocServer_received_data_cb(PurpleConnection *gc, xmlnode **packet, gpointer this) {
AMPurpleJabberAdHocServer *self = this;
PurpleAccount *account = [self.account purpleAccount];
if(purple_account_get_connection(account) == gc) {
if(strcmp((*packet)->name,"iq"))
return;
const char *type = xmlnode_get_attrib(*packet,"type");
if(!type || strcmp(type,"set"))
return; // doesn't talk to us, probably the user interacting with some other adhoc node
const char *from = xmlnode_get_attrib(*packet,"from");
const char *iqid = xmlnode_get_attrib(*packet,"id");
xmlnode *command = xmlnode_get_child_with_namespace(*packet,"command","http://jabber.org/protocol/commands");
if(command) {
BOOL handled = [self receivedCommand:command
from:from?[NSString stringWithUTF8String:from]:nil
iqid:iqid?[NSString stringWithUTF8String:iqid]:nil];
if(handled) {
xmlnode_free(*packet);
*packet = NULL;
}
}
}
}
/* we have to catch the reply to a disco#info for http://jabber.org/protocol/commands and insert our nodes */
static void xmlnode_sent_cb(PurpleConnection *gc, xmlnode **packet, gpointer this) {
xmlnode *xml = *packet;
AMPurpleJabberAdHocServer *self = this;
PurpleAccount *account = [self.account purpleAccount];
if(xml && purple_account_get_connection(account) == gc) {
if(!strcmp(xml->name,"iq")) {
const char *tostr = xmlnode_get_attrib(xml,"to");
if(tostr) {
NSString *to = [NSString stringWithUTF8String:tostr];
NSRange slash = [to rangeOfString:@"/"];
if(slash.location != NSNotFound) {
NSString *barejid = [to substringToIndex:slash.location];
if([barejid isEqualToString:self.account.UID]) {
const char *type = xmlnode_get_attrib(xml,"type");
if(type && !strcmp(type,"result")) {
xmlnode *query = xmlnode_get_child_with_namespace(xml,"query","http://jabber.org/protocol/disco#items");
if(query) {
const char *node = xmlnode_get_attrib(query,"node");
if(node && !strcmp(node,"http://jabber.org/protocol/commands"))
[self addCommandsToXML:query];
}
}
}
}
}
}
}
}
+ (void)initialize {
if (self == [AMPurpleJabberAdHocServer class])
jabber_add_feature("http://jabber.org/protocol/commands", NULL);
}
- (id)initWithAccount:(ESPurpleJabberAccount*)_account {
if((self = [super init])) {
account = _account;
commands = [[NSMutableDictionary alloc] init];
PurplePlugin *jabber = purple_find_prpl("prpl-jabber");
if (!jabber) {
AILog(@"Unable to locate jabber prpl");
[self release];
return nil;
}
purple_signal_connect(jabber, "jabber-receiving-xmlnode", self,
PURPLE_CALLBACK(AMPurpleJabberAdHocServer_received_data_cb), self);
purple_signal_connect(jabber, "jabber-sending-xmlnode", self,
PURPLE_CALLBACK(xmlnode_sent_cb), self);
}
return self;
}
- (void)dealloc {
purple_signals_disconnect_by_handle(self);
[commands release];
[super dealloc];
}
- (void)addCommand:(NSString*)node delegate:(id<AMPurpleJabberAdHocServerDelegate>)delegate name:(NSString*)name {
[commands setObject:[NSDictionary dictionaryWithObjectsAndKeys:
[NSValue valueWithNonretainedObject:delegate],@"delegate",
name, @"name",
nil] forKey:node];
}
- (void)removeCommand:(NSString*)node {
[commands removeObjectForKey:node];
}
- (ESPurpleJabberAccount*)account {
return account;
}
- (void)addCommandsToXML:(xmlnode*)xml {
JabberStream *js = purple_account_get_connection([self.account purpleAccount])->proto_data;
char *jid = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource);
for (NSString *node in commands) {
xmlnode *item = xmlnode_new_child(xml, "item");
xmlnode_set_attrib(item,"jid",jid);
xmlnode_set_attrib(item,"name",[[[commands objectForKey:node] objectForKey:@"name"] UTF8String]);
xmlnode_set_attrib(item,"node",[node UTF8String]);
}
g_free(jid);
}
- (BOOL)receivedCommand:(xmlnode*)command from:(NSString*)jid iqid:(NSString*)iqid {
// verify that it's the same bare jid this command was received from
if(!jid)
return NO;
NSRange slash = [jid rangeOfString:@"/"];
if(slash.location == NSNotFound || ![[jid substringToIndex:slash.location] isEqualToString:account.UID])
return NO;
const char *node = xmlnode_get_attrib(command,"node");
if(node) {
id delegate = [[commands objectForKey:[NSString stringWithUTF8String:node]] objectForKey:@"delegate"];
if(delegate && [[delegate nonretainedObjectValue] respondsToSelector:@selector(adHocServer:executeCommand:)]) {
AMPurpleJabberAdHocCommand *cmd = [[AMPurpleJabberAdHocCommand alloc] initWithServer:self command:command jid:jid iqid:iqid];
[[delegate nonretainedObjectValue] adHocServer:self executeCommand:cmd];
[cmd release];
return YES;
}
}
return NO;
}
@end
|