00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 120675 $")
00037
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <iksemel.h>
00041
00042 #include "asterisk/channel.h"
00043 #include "asterisk/jabber.h"
00044 #include "asterisk/file.h"
00045 #include "asterisk/config.h"
00046 #include "asterisk/callerid.h"
00047 #include "asterisk/lock.h"
00048 #include "asterisk/logger.h"
00049 #include "asterisk/options.h"
00050 #include "asterisk/cli.h"
00051 #include "asterisk/app.h"
00052 #include "asterisk/pbx.h"
00053 #include "asterisk/md5.h"
00054 #include "asterisk/acl.h"
00055 #include "asterisk/utils.h"
00056 #include "asterisk/module.h"
00057 #include "asterisk/astobj.h"
00058 #include "asterisk/astdb.h"
00059 #include "asterisk/manager.h"
00060
00061 #define JABBER_CONFIG "jabber.conf"
00062
00063 #ifndef FALSE
00064 #define FALSE 0
00065 #endif
00066
00067 #ifndef TRUE
00068 #define TRUE 1
00069 #endif
00070
00071
00072 static int aji_highest_bit(int number);
00073 static void aji_buddy_destroy(struct aji_buddy *obj);
00074 static void aji_client_destroy(struct aji_client *obj);
00075 static int aji_send_exec(struct ast_channel *chan, void *data);
00076 static int aji_status_exec(struct ast_channel *chan, void *data);
00077 static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming);
00078 static int aji_act_hook(void *data, int type, iks *node);
00079 static void aji_handle_iq(struct aji_client *client, iks *node);
00080 static void aji_handle_message(struct aji_client *client, ikspak *pak);
00081 static void aji_handle_presence(struct aji_client *client, ikspak *pak);
00082 static void aji_handle_subscribe(struct aji_client *client, ikspak *pak);
00083 static void *aji_recv_loop(void *data);
00084 static int aji_component_initialize(struct aji_client *client);
00085 static int aji_client_initialize(struct aji_client *client);
00086 static int aji_client_connect(void *data, ikspak *pak);
00087 static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc);
00088 static int aji_do_debug(int fd, int argc, char *argv[]);
00089 static int aji_do_reload(int fd, int argc, char *argv[]);
00090 static int aji_no_debug(int fd, int argc, char *argv[]);
00091 static int aji_test(int fd, int argc, char *argv[]);
00092 static int aji_show_clients(int fd, int argc, char *argv[]);
00093 static int aji_create_client(char *label, struct ast_variable *var, int debug);
00094 static int aji_create_buddy(char *label, struct aji_client *client);
00095 static int aji_reload(void);
00096 static int aji_load_config(void);
00097 static void aji_pruneregister(struct aji_client *client);
00098 static int aji_filter_roster(void *data, ikspak *pak);
00099 static int aji_get_roster(struct aji_client *client);
00100 static int aji_client_info_handler(void *data, ikspak *pak);
00101 static int aji_dinfo_handler(void *data, ikspak *pak);
00102 static int aji_ditems_handler(void *data, ikspak *pak);
00103 static int aji_register_query_handler(void *data, ikspak *pak);
00104 static int aji_register_approve_handler(void *data, ikspak *pak);
00105 static int aji_reconnect(struct aji_client *client);
00106 static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid);
00107
00108
00109
00110
00111
00112
00113
00114 static char debug_usage[] =
00115 "Usage: jabber debug\n"
00116 " Enables dumping of Jabber packets for debugging purposes.\n";
00117
00118 static char no_debug_usage[] =
00119 "Usage: jabber debug off\n"
00120 " Disables dumping of Jabber packets for debugging purposes.\n";
00121
00122 static char reload_usage[] =
00123 "Usage: jabber reload\n"
00124 " Enables reloading of Jabber module.\n";
00125
00126 static char test_usage[] =
00127 "Usage: jabber test [client]\n"
00128 " Sends test message for debugging purposes. A specific client\n"
00129 " as configured in jabber.conf can be optionally specified.\n";
00130
00131 static struct ast_cli_entry aji_cli[] = {
00132 { { "jabber", "debug", NULL},
00133 aji_do_debug, "Enable Jabber debugging",
00134 debug_usage },
00135
00136 { { "jabber", "reload", NULL},
00137 aji_do_reload, "Reload Jabber configuration",
00138 reload_usage },
00139
00140 { { "jabber", "show", "connected", NULL},
00141 aji_show_clients, "Show state of clients and components",
00142 debug_usage },
00143
00144 { { "jabber", "debug", "off", NULL},
00145 aji_no_debug, "Disable Jabber debug",
00146 no_debug_usage },
00147
00148 { { "jabber", "test", NULL},
00149 aji_test, "Shows roster, but is generally used for mog's debugging.",
00150 test_usage },
00151 };
00152
00153 static char *app_ajisend = "JabberSend";
00154
00155 static char *ajisend_synopsis = "JabberSend(jabber,screenname,message)";
00156
00157 static char *ajisend_descrip =
00158 "JabberSend(Jabber,ScreenName,Message)\n"
00159 " Jabber - Client or transport Asterisk uses to connect to Jabber\n"
00160 " ScreenName - User Name to message.\n"
00161 " Message - Message to be sent to the buddy\n";
00162
00163 static char *app_ajistatus = "JabberStatus";
00164
00165 static char *ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)";
00166
00167 static char *ajistatus_descrip =
00168 "JabberStatus(Jabber,ScreenName,Variable)\n"
00169 " Jabber - Client or transport Asterisk uses to connect to Jabber\n"
00170 " ScreenName - User Name to retrieve status from.\n"
00171 " Variable - Variable to store presence in will be 1-6.\n"
00172 " In order, Online, Chatty, Away, XAway, DND, Offline\n"
00173 " If not in roster variable will = 7\n";
00174
00175 struct aji_client_container clients;
00176 struct aji_capabilities *capabilities = NULL;
00177
00178
00179 static struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER };
00180 static int tls_initialized = FALSE;
00181
00182
00183
00184
00185
00186
00187 static void aji_client_destroy(struct aji_client *obj)
00188 {
00189 struct aji_message *tmp;
00190 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy);
00191 ASTOBJ_CONTAINER_DESTROY(&obj->buddies);
00192 iks_filter_delete(obj->f);
00193 iks_parser_delete(obj->p);
00194 iks_stack_delete(obj->stack);
00195 AST_LIST_LOCK(&obj->messages);
00196 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) {
00197 if (tmp->from)
00198 free(tmp->from);
00199 if (tmp->message)
00200 free(tmp->message);
00201 }
00202 AST_LIST_HEAD_DESTROY(&obj->messages);
00203 free(obj);
00204 }
00205
00206
00207
00208
00209
00210
00211 static void aji_buddy_destroy(struct aji_buddy *obj)
00212 {
00213 struct aji_resource *tmp;
00214
00215 while ((tmp = obj->resources)) {
00216 obj->resources = obj->resources->next;
00217 free(tmp->description);
00218 free(tmp);
00219 }
00220
00221 free(obj);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 static struct aji_version *aji_find_version(char *node, char *version, ikspak *pak)
00234 {
00235 struct aji_capabilities *list = NULL;
00236 struct aji_version *res = NULL;
00237
00238 list = capabilities;
00239
00240 if(!node)
00241 node = pak->from->full;
00242 if(!version)
00243 version = "none supplied.";
00244 while(list) {
00245 if(!strcasecmp(list->node, node)) {
00246 res = list->versions;
00247 while(res) {
00248 if(!strcasecmp(res->version, version))
00249 return res;
00250 res = res->next;
00251 }
00252
00253
00254 if(!res) {
00255 res = (struct aji_version *)malloc(sizeof(struct aji_version));
00256 if(!res) {
00257 ast_log(LOG_ERROR, "Out of memory!\n");
00258 return NULL;
00259 }
00260 res->jingle = 0;
00261 res->parent = list;
00262 ast_copy_string(res->version, version, sizeof(res->version));
00263 res->next = list->versions;
00264 list->versions = res;
00265 return res;
00266 }
00267 }
00268 list = list->next;
00269 }
00270
00271 if(!list) {
00272 list = (struct aji_capabilities *)malloc(sizeof(struct aji_capabilities));
00273 if(!list) {
00274 ast_log(LOG_ERROR, "Out of memory!\n");
00275 return NULL;
00276 }
00277 res = (struct aji_version *)malloc(sizeof(struct aji_version));
00278 if(!res) {
00279 ast_log(LOG_ERROR, "Out of memory!\n");
00280 ast_free(list);
00281 return NULL;
00282 }
00283 ast_copy_string(list->node, node, sizeof(list->node));
00284 ast_copy_string(res->version, version, sizeof(res->version));
00285 res->jingle = 0;
00286 res->parent = list;
00287 res->next = NULL;
00288 list->versions = res;
00289 list->next = capabilities;
00290 capabilities = list;
00291 }
00292 return res;
00293 }
00294
00295 static struct aji_resource *aji_find_resource(struct aji_buddy *buddy, char *name)
00296 {
00297 struct aji_resource *res = NULL;
00298 if (!buddy || !name)
00299 return res;
00300 res = buddy->resources;
00301 while (res) {
00302 if (!strcasecmp(res->resource, name)) {
00303 break;
00304 }
00305 res = res->next;
00306 }
00307 return res;
00308 }
00309
00310 static int gtalk_yuck(iks *node)
00311 {
00312 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps"))
00313 return 1;
00314 return 0;
00315 }
00316
00317
00318
00319
00320
00321
00322 static int aji_highest_bit(int number)
00323 {
00324 int x = sizeof(number) * 8 - 1;
00325 if (!number)
00326 return 0;
00327 for (; x > 0; x--) {
00328 if (number & (1 << x))
00329 break;
00330 }
00331 return (1 << x);
00332 }
00333
00334 static iks *jabber_make_auth(iksid * id, const char *pass, const char *sid)
00335 {
00336 iks *x, *y;
00337 x = iks_new("iq");
00338 iks_insert_attrib(x, "type", "set");
00339 y = iks_insert(x, "query");
00340 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH);
00341 iks_insert_cdata(iks_insert(y, "username"), id->user, 0);
00342 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0);
00343 if (sid) {
00344 char buf[41];
00345 char sidpass[100];
00346 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass);
00347 ast_sha1_hash(buf, sidpass);
00348 iks_insert_cdata(iks_insert(y, "digest"), buf, 0);
00349 } else {
00350 iks_insert_cdata(iks_insert(y, "password"), pass, 0);
00351 }
00352 return x;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361 static int aji_status_exec(struct ast_channel *chan, void *data)
00362 {
00363 struct aji_client *client = NULL;
00364 struct aji_buddy *buddy = NULL;
00365 struct aji_resource *r = NULL;
00366 char *s = NULL, *sender = NULL, *jid = NULL, *screenname = NULL, *resource = NULL, *variable = NULL;
00367 int stat = 7;
00368 char status[2];
00369
00370 if (!data) {
00371 ast_log(LOG_ERROR, "This application requires arguments.\n");
00372 return 0;
00373 }
00374 s = ast_strdupa(data);
00375 if (s) {
00376 sender = strsep(&s, "|");
00377 if (sender && (sender[0] != '\0')) {
00378 jid = strsep(&s, "|");
00379 if (jid && (jid[0] != '\0')) {
00380 variable = s;
00381 } else {
00382 ast_log(LOG_ERROR, "Bad arguments\n");
00383 return -1;
00384 }
00385 }
00386 }
00387
00388 if(!strchr(jid, '/')) {
00389 resource = NULL;
00390 } else {
00391 screenname = strsep(&jid, "/");
00392 resource = jid;
00393 }
00394 client = ast_aji_get_client(sender);
00395 if (!client) {
00396 ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
00397 return -1;
00398 }
00399 if(!&client->buddies) {
00400 ast_log(LOG_WARNING, "No buddies for connection : %s\n", sender);
00401 return -1;
00402 }
00403 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, resource ? screenname: jid);
00404 if (!buddy) {
00405 ast_log(LOG_WARNING, "Could not find buddy in list : %s\n", resource ? screenname : jid);
00406 return -1;
00407 }
00408 r = aji_find_resource(buddy, resource);
00409 if(!r && buddy->resources)
00410 r = buddy->resources;
00411 if(!r)
00412 ast_log(LOG_NOTICE, "Resource %s of buddy %s not found \n", resource, screenname);
00413 else
00414 stat = r->status;
00415 sprintf(status, "%d", stat);
00416 pbx_builtin_setvar_helper(chan, variable, status);
00417 return 0;
00418 }
00419
00420
00421
00422
00423
00424
00425 static int aji_send_exec(struct ast_channel *chan, void *data)
00426 {
00427 struct aji_client *client = NULL;
00428
00429 char *s = NULL, *sender = NULL, *recipient = NULL, *message = NULL;
00430
00431 if (!data) {
00432 ast_log(LOG_ERROR, "This application requires arguments.\n");
00433 return 0;
00434 }
00435 s = ast_strdupa(data);
00436 if (s) {
00437 sender = strsep(&s, "|");
00438 if (sender && (sender[0] != '\0')) {
00439 recipient = strsep(&s, "|");
00440 if (recipient && (recipient[0] != '\0')) {
00441 message = s;
00442 } else {
00443 ast_log(LOG_ERROR, "Bad arguments: %s\n", (char *) data);
00444 return -1;
00445 }
00446 }
00447 }
00448 if (!(client = ast_aji_get_client(sender))) {
00449 ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
00450 return -1;
00451 }
00452 if (strchr(recipient, '@') && message)
00453 ast_aji_send(client, recipient, message);
00454 return 0;
00455 }
00456
00457
00458
00459
00460
00461 static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming)
00462 {
00463 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00464 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp);
00465
00466 if (client->debug) {
00467 if (is_incoming)
00468 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp);
00469 else {
00470 if( strlen(xmpp) == 1) {
00471 if(option_debug > 2 && xmpp[0] == ' ')
00472 ast_verbose("\nJABBER: Keep alive packet\n");
00473 } else
00474 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp);
00475 }
00476
00477 }
00478 ASTOBJ_UNREF(client, aji_client_destroy);
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488 static int aji_act_hook(void *data, int type, iks *node)
00489 {
00490 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00491 ikspak *pak = NULL;
00492 iks *auth = NULL;
00493
00494 if(!node) {
00495 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n");
00496 ASTOBJ_UNREF(client, aji_client_destroy);
00497 return IKS_HOOK;
00498 }
00499
00500 if (client->state == AJI_DISCONNECTING) {
00501 ASTOBJ_UNREF(client, aji_client_destroy);
00502 return IKS_HOOK;
00503 }
00504
00505 pak = iks_packet(node);
00506
00507 if (!client->component) {
00508 switch (type) {
00509 case IKS_NODE_START:
00510 if (client->usetls && !iks_is_secure(client->p)) {
00511 if (iks_has_tls()) {
00512 iks_start_tls(client->p);
00513 tls_initialized = TRUE;
00514 } else
00515 ast_log(LOG_ERROR, "gnuTLS not installed. You need to recompile the Iksemel library with gnuTLS support\n");
00516 break;
00517 }
00518 if (!client->usesasl) {
00519 iks_filter_add_rule(client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, IKS_RULE_DONE);
00520 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id"));
00521 if (auth) {
00522 iks_insert_attrib(auth, "id", client->mid);
00523 iks_insert_attrib(auth, "to", client->jid->server);
00524 ast_aji_increment_mid(client->mid);
00525 iks_send(client->p, auth);
00526 iks_delete(auth);
00527 } else
00528 ast_log(LOG_ERROR, "Out of memory.\n");
00529 }
00530 break;
00531
00532 case IKS_NODE_NORMAL:
00533 if (!strcmp("stream:features", iks_name(node))) {
00534 int features = 0;
00535 features = iks_stream_features(node);
00536 if (client->usesasl) {
00537 if (client->usetls && !iks_is_secure(client->p))
00538 break;
00539 if (client->authorized) {
00540 if (features & IKS_STREAM_BIND) {
00541 iks_filter_add_rule (client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_DONE);
00542 auth = iks_make_resource_bind(client->jid);
00543 if (auth) {
00544 iks_insert_attrib(auth, "id", client->mid);
00545 ast_aji_increment_mid(client->mid);
00546 iks_send(client->p, auth);
00547 iks_delete(auth);
00548 } else {
00549 ast_log(LOG_ERROR, "Out of memory.\n");
00550 break;
00551 }
00552 }
00553 if (features & IKS_STREAM_SESSION) {
00554 iks_filter_add_rule (client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "auth", IKS_RULE_DONE);
00555 auth = iks_make_session();
00556 if (auth) {
00557 iks_insert_attrib(auth, "id", "auth");
00558 ast_aji_increment_mid(client->mid);
00559 iks_send(client->p, auth);
00560 iks_delete(auth);
00561 } else {
00562 ast_log(LOG_ERROR, "Out of memory.\n");
00563 }
00564 }
00565 } else {
00566 if (!client->jid->user) {
00567 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full);
00568 break;
00569 }
00570 features = aji_highest_bit(features);
00571 if (features == IKS_STREAM_SASL_MD5)
00572 iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, client->jid->user, client->password);
00573 else {
00574 if (features == IKS_STREAM_SASL_PLAIN) {
00575 iks *x = NULL;
00576 x = iks_new("auth");
00577 if (x) {
00578 int len = strlen(client->jid->user) + strlen(client->password) + 3;
00579
00580 char *s = ast_malloc(80 + len);
00581 char *base64 = ast_malloc(80 + len * 2);
00582 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL);
00583 iks_insert_attrib(x, "mechanism", "PLAIN");
00584 sprintf(s, "%c%s%c%s", 0, client->jid->user, 0, client->password);
00585
00586
00587
00588
00589
00590 ast_base64encode(base64, (const unsigned char *) s, len - 1, len * 2);
00591 iks_insert_cdata(x, base64, 0);
00592 iks_send(client->p, x);
00593 iks_delete(x);
00594 if (base64)
00595 free(base64);
00596 if (s)
00597 free(s);
00598 } else {
00599 ast_log(LOG_ERROR, "Out of memory.\n");
00600 }
00601 }
00602 }
00603 }
00604 }
00605 } else if (!strcmp("failure", iks_name(node))) {
00606 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
00607 } else if (!strcmp("success", iks_name(node))) {
00608 client->authorized = 1;
00609 iks_send_header(client->p, client->jid->server);
00610 }
00611 break;
00612 case IKS_NODE_ERROR:
00613 ast_log(LOG_ERROR, "JABBER: Node Error\n");
00614 ASTOBJ_UNREF(client, aji_client_destroy);
00615 return IKS_HOOK;
00616 break;
00617 case IKS_NODE_STOP:
00618 ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00619 ASTOBJ_UNREF(client, aji_client_destroy);
00620 return IKS_HOOK;
00621 break;
00622 }
00623 } else if (client->state != AJI_CONNECTED && client->component) {
00624 switch (type) {
00625 case IKS_NODE_START:
00626 if (client->state == AJI_DISCONNECTED) {
00627 char secret[160], shasum[320], *handshake;
00628
00629 sprintf(secret, "%s%s", pak->id, client->password);
00630 ast_sha1_hash(shasum, secret);
00631 handshake = NULL;
00632 asprintf(&handshake, "<handshake>%s</handshake>", shasum);
00633 if (handshake) {
00634 iks_send_raw(client->p, handshake);
00635 free(handshake);
00636 handshake = NULL;
00637 }
00638 client->state = AJI_CONNECTING;
00639 if(iks_recv(client->p,1) == 2)
00640 client->state = AJI_CONNECTED;
00641 else
00642 ast_log(LOG_WARNING,"Jabber didn't seem to handshake, failed to authenicate.\n");
00643 break;
00644 }
00645 break;
00646
00647 case IKS_NODE_NORMAL:
00648 break;
00649
00650 case IKS_NODE_ERROR:
00651 ast_log(LOG_ERROR, "JABBER: Node Error\n");
00652 ASTOBJ_UNREF(client, aji_client_destroy);
00653 return IKS_HOOK;
00654
00655 case IKS_NODE_STOP:
00656 ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00657 ASTOBJ_UNREF(client, aji_client_destroy);
00658 return IKS_HOOK;
00659 }
00660 }
00661
00662 switch (pak->type) {
00663 case IKS_PAK_NONE:
00664 if (option_debug)
00665 ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you NONE\n");
00666 break;
00667 case IKS_PAK_MESSAGE:
00668 aji_handle_message(client, pak);
00669 if (option_debug)
00670 ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you MESSAGE\n");
00671 break;
00672 case IKS_PAK_PRESENCE:
00673 aji_handle_presence(client, pak);
00674 if (option_debug)
00675 ast_log(LOG_DEBUG, "JABBER: I Do know how to handle presence!!\n");
00676 break;
00677 case IKS_PAK_S10N:
00678 aji_handle_subscribe(client, pak);
00679 if (option_debug)
00680 ast_log(LOG_DEBUG, "JABBER: I Dont know S10N subscribe!!\n");
00681 break;
00682 case IKS_PAK_IQ:
00683 if (option_debug)
00684 ast_log(LOG_DEBUG, "JABBER: I Dont have an IQ!!!\n");
00685 aji_handle_iq(client, node);
00686 break;
00687 default:
00688 if (option_debug)
00689 ast_log(LOG_DEBUG, "JABBER: I Dont know %i\n", pak->type);
00690 break;
00691 }
00692
00693 iks_filter_packet(client->f, pak);
00694
00695 if (node)
00696 iks_delete(node);
00697
00698 ASTOBJ_UNREF(client, aji_client_destroy);
00699 return IKS_OK;
00700 }
00701
00702 static int aji_register_approve_handler(void *data, ikspak *pak)
00703 {
00704 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00705 iks *iq = NULL, *presence = NULL, *x = NULL;
00706
00707 iq = iks_new("iq");
00708 presence = iks_new("presence");
00709 x = iks_new("x");
00710 if (client && iq && presence && x) {
00711 if (!iks_find(pak->query, "remove")) {
00712 iks_insert_attrib(iq, "from", client->jid->full);
00713 iks_insert_attrib(iq, "to", pak->from->full);
00714 iks_insert_attrib(iq, "id", pak->id);
00715 iks_insert_attrib(iq, "type", "result");
00716 iks_send(client->p, iq);
00717
00718 iks_insert_attrib(presence, "from", client->jid->full);
00719 iks_insert_attrib(presence, "to", pak->from->partial);
00720 iks_insert_attrib(presence, "id", client->mid);
00721 ast_aji_increment_mid(client->mid);
00722 iks_insert_attrib(presence, "type", "subscribe");
00723 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
00724 iks_insert_node(presence, x);
00725 iks_send(client->p, presence);
00726 }
00727 } else {
00728 ast_log(LOG_ERROR, "Out of memory.\n");
00729 }
00730
00731 if (iq)
00732 iks_delete(iq);
00733 if(presence)
00734 iks_delete(presence);
00735 if (x)
00736 iks_delete(x);
00737 ASTOBJ_UNREF(client, aji_client_destroy);
00738 return IKS_FILTER_EAT;
00739 }
00740
00741 static int aji_register_query_handler(void *data, ikspak *pak)
00742 {
00743 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00744 struct aji_buddy *buddy = NULL;
00745 char *node = NULL;
00746
00747 client = (struct aji_client *) data;
00748
00749 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00750 if (!buddy) {
00751 iks *iq = NULL, *query = NULL, *error = NULL, *notacceptable = NULL;
00752 ast_verbose("Someone.... %s tried to register but they aren't allowed\n", pak->from->partial);
00753 iq = iks_new("iq");
00754 query = iks_new("query");
00755 error = iks_new("error");
00756 notacceptable = iks_new("not-acceptable");
00757 if(iq && query && error && notacceptable) {
00758 iks_insert_attrib(iq, "type", "error");
00759 iks_insert_attrib(iq, "from", client->user);
00760 iks_insert_attrib(iq, "to", pak->from->full);
00761 iks_insert_attrib(iq, "id", pak->id);
00762 iks_insert_attrib(query, "xmlns", "jabber:iq:register");
00763 iks_insert_attrib(error, "code" , "406");
00764 iks_insert_attrib(error, "type", "modify");
00765 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
00766 iks_insert_node(iq, query);
00767 iks_insert_node(iq, error);
00768 iks_insert_node(error, notacceptable);
00769 iks_send(client->p, iq);
00770 } else {
00771 ast_log(LOG_ERROR, "Out of memory.\n");
00772 }
00773 if (iq)
00774 iks_delete(iq);
00775 if (query)
00776 iks_delete(query);
00777 if (error)
00778 iks_delete(error);
00779 if (notacceptable)
00780 iks_delete(notacceptable);
00781 } else if (!(node = iks_find_attrib(pak->query, "node"))) {
00782 iks *iq = NULL, *query = NULL, *instructions = NULL;
00783 char *explain = "Welcome to Asterisk - the Open Source PBX.\n";
00784 iq = iks_new("iq");
00785 query = iks_new("query");
00786 instructions = iks_new("instructions");
00787 if (iq && query && instructions && client) {
00788 iks_insert_attrib(iq, "from", client->user);
00789 iks_insert_attrib(iq, "to", pak->from->full);
00790 iks_insert_attrib(iq, "id", pak->id);
00791 iks_insert_attrib(iq, "type", "result");
00792 iks_insert_attrib(query, "xmlns", "jabber:iq:register");
00793 iks_insert_cdata(instructions, explain, 0);
00794 iks_insert_node(iq, query);
00795 iks_insert_node(query, instructions);
00796 iks_send(client->p, iq);
00797 } else {
00798 ast_log(LOG_ERROR, "Out of memory.\n");
00799 }
00800 if (iq)
00801 iks_delete(iq);
00802 if (query)
00803 iks_delete(query);
00804 if (instructions)
00805 iks_delete(instructions);
00806 }
00807 ASTOBJ_UNREF(client, aji_client_destroy);
00808 return IKS_FILTER_EAT;
00809 }
00810
00811 static int aji_ditems_handler(void *data, ikspak *pak)
00812 {
00813 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00814 char *node = NULL;
00815
00816 if (!(node = iks_find_attrib(pak->query, "node"))) {
00817 iks *iq = NULL, *query = NULL, *item = NULL;
00818 iq = iks_new("iq");
00819 query = iks_new("query");
00820 item = iks_new("item");
00821
00822 if (iq && query && item) {
00823 iks_insert_attrib(iq, "from", client->user);
00824 iks_insert_attrib(iq, "to", pak->from->full);
00825 iks_insert_attrib(iq, "id", pak->id);
00826 iks_insert_attrib(iq, "type", "result");
00827 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00828 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands");
00829 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands");
00830 iks_insert_attrib(item, "jid", client->user);
00831
00832 iks_insert_node(iq, query);
00833 iks_insert_node(query, item);
00834 iks_send(client->p, iq);
00835 } else {
00836 ast_log(LOG_ERROR, "Out of memory.\n");
00837 }
00838 if (iq)
00839 iks_delete(iq);
00840 if (query)
00841 iks_delete(query);
00842 if (item)
00843 iks_delete(item);
00844
00845 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
00846 iks *iq, *query, *confirm;
00847 iq = iks_new("iq");
00848 query = iks_new("query");
00849 confirm = iks_new("item");
00850 if (iq && query && confirm && client) {
00851 iks_insert_attrib(iq, "from", client->user);
00852 iks_insert_attrib(iq, "to", pak->from->full);
00853 iks_insert_attrib(iq, "id", pak->id);
00854 iks_insert_attrib(iq, "type", "result");
00855 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00856 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
00857 iks_insert_attrib(confirm, "node", "confirmaccount");
00858 iks_insert_attrib(confirm, "name", "Confirm AIM account");
00859 iks_insert_attrib(confirm, "jid", "blog.astjab.org");
00860
00861 iks_insert_node(iq, query);
00862 iks_insert_node(query, confirm);
00863 iks_send(client->p, iq);
00864 } else {
00865 ast_log(LOG_ERROR, "Out of memory.\n");
00866 }
00867 if (iq)
00868 iks_delete(iq);
00869 if (query)
00870 iks_delete(query);
00871 if (confirm)
00872 iks_delete(confirm);
00873
00874 } else if (!strcasecmp(node, "confirmaccount")) {
00875 iks *iq = NULL, *query = NULL, *feature = NULL;
00876
00877 iq = iks_new("iq");
00878 query = iks_new("query");
00879 feature = iks_new("feature");
00880
00881 if (iq && query && feature && client) {
00882 iks_insert_attrib(iq, "from", client->user);
00883 iks_insert_attrib(iq, "to", pak->from->full);
00884 iks_insert_attrib(iq, "id", pak->id);
00885 iks_insert_attrib(iq, "type", "result");
00886 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00887 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
00888 iks_insert_node(iq, query);
00889 iks_insert_node(query, feature);
00890 iks_send(client->p, iq);
00891 } else {
00892 ast_log(LOG_ERROR, "Out of memory.\n");
00893 }
00894 if (iq)
00895 iks_delete(iq);
00896 if (query)
00897 iks_delete(query);
00898 if (feature)
00899 iks_delete(feature);
00900 }
00901
00902 ASTOBJ_UNREF(client, aji_client_destroy);
00903 return IKS_FILTER_EAT;
00904
00905 }
00906
00907 static int aji_client_info_handler(void *data, ikspak *pak)
00908 {
00909 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00910 struct aji_resource *resource = NULL;
00911 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00912
00913 resource = aji_find_resource(buddy, pak->from->resource);
00914 if (pak->subtype == IKS_TYPE_RESULT) {
00915 if (!resource) {
00916 ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
00917 ASTOBJ_UNREF(client, aji_client_destroy);
00918 return IKS_FILTER_EAT;
00919 }
00920 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
00921 resource->cap->jingle = 1;
00922 } else
00923 resource->cap->jingle = 0;
00924 } else if (pak->subtype == IKS_TYPE_GET) {
00925 iks *iq, *disco, *ident, *google, *query;
00926 iq = iks_new("iq");
00927 query = iks_new("query");
00928 ident = iks_new("identity");
00929 disco = iks_new("feature");
00930 google = iks_new("feature");
00931 if (iq && ident && disco && google) {
00932 iks_insert_attrib(iq, "from", client->jid->full);
00933 iks_insert_attrib(iq, "to", pak->from->full);
00934 iks_insert_attrib(iq, "type", "result");
00935 iks_insert_attrib(iq, "id", pak->id);
00936 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
00937 iks_insert_attrib(ident, "category", "client");
00938 iks_insert_attrib(ident, "type", "pc");
00939 iks_insert_attrib(ident, "name", "asterisk");
00940 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info");
00941 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1");
00942 iks_insert_node(iq, query);
00943 iks_insert_node(query, ident);
00944 iks_insert_node(query, google);
00945 iks_insert_node(query, disco);
00946 iks_send(client->p, iq);
00947 } else
00948 ast_log(LOG_ERROR, "Out of Memory.\n");
00949 if (iq)
00950 iks_delete(iq);
00951 if (query)
00952 iks_delete(query);
00953 if (ident)
00954 iks_delete(ident);
00955 if (google)
00956 iks_delete(google);
00957 if (disco)
00958 iks_delete(disco);
00959 } else if (pak->subtype == IKS_TYPE_ERROR) {
00960 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full);
00961 }
00962 ASTOBJ_UNREF(client, aji_client_destroy);
00963 return IKS_FILTER_EAT;
00964 }
00965
00966 static int aji_dinfo_handler(void *data, ikspak *pak)
00967 {
00968 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00969 char *node = NULL;
00970 struct aji_resource *resource = NULL;
00971 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00972
00973 resource = aji_find_resource(buddy, pak->from->resource);
00974 if (pak->subtype == IKS_TYPE_ERROR) {
00975 ast_log(LOG_WARNING, "Recieved error from a client, turn on jabber debug!\n");
00976 return IKS_FILTER_EAT;
00977 }
00978 if (pak->subtype == IKS_TYPE_RESULT) {
00979 if (!resource) {
00980 ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
00981