| 36530:b8caab360c96 | 36531:6d45c74af198 |
|---|---|
| 69 I don't know why I even bother providing these. Oh valiant reader, | 69 I don't know why I even bother providing these. Oh valiant reader, |
| 70 I do it all for you. */ | 70 I do it all for you. */ |
| 71 /* scratch that, I just added it to the prpl options panel */ | 71 /* scratch that, I just added it to the prpl options panel */ |
| 72 #define PLUGIN_ID "prpl-meanwhile" | 72 #define PLUGIN_ID "prpl-meanwhile" |
| 73 #define PLUGIN_NAME "Sametime" | 73 #define PLUGIN_NAME "Sametime" |
| 74 #define PLUGIN_CATEGORY "Protocol" | |
| 74 #define PLUGIN_SUMMARY "Sametime Protocol Plugin" | 75 #define PLUGIN_SUMMARY "Sametime Protocol Plugin" |
| 75 #define PLUGIN_DESC "Open implementation of a Lotus Sametime client" | 76 #define PLUGIN_DESC "Open implementation of a Lotus Sametime client" |
| 76 #define PLUGIN_AUTHOR "Christopher (siege) O'Brien <siege@preoccupied.net>" | 77 #define PLUGIN_AUTHOR "Christopher (siege) O'Brien <siege@preoccupied.net>" |
| 77 #define PLUGIN_HOMEPAGE "http://meanwhile.sourceforge.net/" | 78 #define PLUGIN_HOMEPAGE "http://meanwhile.sourceforge.net/" |
| 78 | 79 |
| 195 static guint log_handler[2] = { 0, 0 }; | 196 static guint log_handler[2] = { 0, 0 }; |
| 196 | 197 |
| 197 | 198 |
| 198 /** the purple plugin data. | 199 /** the purple plugin data. |
| 199 available as purple_connection_get_protocol_data(gc) and mwSession_getClientData */ | 200 available as purple_connection_get_protocol_data(gc) and mwSession_getClientData */ |
| 200 struct mwPurplePluginData { | 201 struct mwPurpleProtocolData { |
| 201 struct mwSession *session; | 202 struct mwSession *session; |
| 202 | 203 |
| 203 struct mwServiceAware *srvc_aware; | 204 struct mwServiceAware *srvc_aware; |
| 204 struct mwServiceConference *srvc_conf; | 205 struct mwServiceConference *srvc_conf; |
| 205 struct mwServiceFileTransfer *srvc_ft; | 206 struct mwServiceFileTransfer *srvc_ft; |
| 234 | 235 |
| 235 /* blist and aware functions */ | 236 /* blist and aware functions */ |
| 236 | 237 |
| 237 static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist); | 238 static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist); |
| 238 | 239 |
| 239 static void blist_store(struct mwPurplePluginData *pd); | 240 static void blist_store(struct mwPurpleProtocolData *pd); |
| 240 | 241 |
| 241 static void blist_schedule(struct mwPurplePluginData *pd); | 242 static void blist_schedule(struct mwPurpleProtocolData *pd); |
| 242 | 243 |
| 243 static void blist_merge(PurpleConnection *gc, struct mwSametimeList *stlist); | 244 static void blist_merge(PurpleConnection *gc, struct mwSametimeList *stlist); |
| 244 | 245 |
| 245 static void blist_sync(PurpleConnection *gc, struct mwSametimeList *stlist); | 246 static void blist_sync(PurpleConnection *gc, struct mwSametimeList *stlist); |
| 246 | 247 |
| 247 static gboolean buddy_is_external(PurpleBuddy *b); | 248 static gboolean buddy_is_external(PurpleBuddy *b); |
| 248 | 249 |
| 249 static void buddy_add(struct mwPurplePluginData *pd, PurpleBuddy *buddy); | 250 static void buddy_add(struct mwPurpleProtocolData *pd, PurpleBuddy *buddy); |
| 250 | 251 |
| 251 static PurpleBuddy * | 252 static PurpleBuddy * |
| 252 buddy_ensure(PurpleConnection *gc, PurpleGroup *group, | 253 buddy_ensure(PurpleConnection *gc, PurpleGroup *group, |
| 253 struct mwSametimeUser *stuser); | 254 struct mwSametimeUser *stuser); |
| 254 | 255 |
| 255 static void group_add(struct mwPurplePluginData *pd, PurpleGroup *group); | 256 static void group_add(struct mwPurpleProtocolData *pd, PurpleGroup *group); |
| 256 | 257 |
| 257 static PurpleGroup * | 258 static PurpleGroup * |
| 258 group_ensure(PurpleConnection *gc, struct mwSametimeGroup *stgroup); | 259 group_ensure(PurpleConnection *gc, struct mwSametimeGroup *stgroup); |
| 259 | 260 |
| 260 static struct mwAwareList * | 261 static struct mwAwareList * |
| 261 list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group); | 262 list_ensure(struct mwPurpleProtocolData *pd, PurpleGroup *group); |
| 262 | 263 |
| 263 | 264 |
| 264 /* session functions */ | 265 /* session functions */ |
| 265 | 266 |
| 266 static struct mwSession * | 267 static struct mwSession * |
| 270 | 271 |
| 271 | 272 |
| 272 /* conference functions */ | 273 /* conference functions */ |
| 273 | 274 |
| 274 static struct mwConference * | 275 static struct mwConference * |
| 275 conf_find_by_id(struct mwPurplePluginData *pd, int id); | 276 conf_find_by_id(struct mwPurpleProtocolData *pd, int id); |
| 276 | 277 |
| 277 | 278 |
| 278 /* conversation functions */ | 279 /* conversation functions */ |
| 279 | 280 |
| 280 struct convo_msg { | 281 struct convo_msg { |
| 314 /* ----- session ------ */ | 315 /* ----- session ------ */ |
| 315 | 316 |
| 316 | 317 |
| 317 /** resolves a mwSession from a PurpleConnection */ | 318 /** resolves a mwSession from a PurpleConnection */ |
| 318 static struct mwSession *gc_to_session(PurpleConnection *gc) { | 319 static struct mwSession *gc_to_session(PurpleConnection *gc) { |
| 319 struct mwPurplePluginData *pd; | 320 struct mwPurpleProtocolData *pd; |
| 320 | 321 |
| 321 g_return_val_if_fail(gc != NULL, NULL); | 322 g_return_val_if_fail(gc != NULL, NULL); |
| 322 | 323 |
| 323 pd = purple_connection_get_protocol_data(gc); | 324 pd = purple_connection_get_protocol_data(gc); |
| 324 g_return_val_if_fail(pd != NULL, NULL); | 325 g_return_val_if_fail(pd != NULL, NULL); |
| 327 } | 328 } |
| 328 | 329 |
| 329 | 330 |
| 330 /** resolves a PurpleConnection from a mwSession */ | 331 /** resolves a PurpleConnection from a mwSession */ |
| 331 static PurpleConnection *session_to_gc(struct mwSession *session) { | 332 static PurpleConnection *session_to_gc(struct mwSession *session) { |
| 332 struct mwPurplePluginData *pd; | 333 struct mwPurpleProtocolData *pd; |
| 333 | 334 |
| 334 g_return_val_if_fail(session != NULL, NULL); | 335 g_return_val_if_fail(session != NULL, NULL); |
| 335 | 336 |
| 336 pd = mwSession_getClientData(session); | 337 pd = mwSession_getClientData(session); |
| 337 g_return_val_if_fail(pd != NULL, NULL); | 338 g_return_val_if_fail(pd != NULL, NULL); |
| 339 return pd->gc; | 340 return pd->gc; |
| 340 } | 341 } |
| 341 | 342 |
| 342 | 343 |
| 343 static void write_cb(gpointer data, gint source, PurpleInputCondition cond) { | 344 static void write_cb(gpointer data, gint source, PurpleInputCondition cond) { |
| 344 struct mwPurplePluginData *pd = data; | 345 struct mwPurpleProtocolData *pd = data; |
| 345 PurpleCircularBuffer *circ = pd->sock_buf; | 346 PurpleCircularBuffer *circ = pd->sock_buf; |
| 346 gsize avail; | 347 gsize avail; |
| 347 int ret; | 348 int ret; |
| 348 | 349 |
| 349 DEBUG_INFO("write_cb\n"); | 350 DEBUG_INFO("write_cb\n"); |
| 371 } | 372 } |
| 372 | 373 |
| 373 | 374 |
| 374 static int mw_session_io_write(struct mwSession *session, | 375 static int mw_session_io_write(struct mwSession *session, |
| 375 const guchar *buf, gsize len) { | 376 const guchar *buf, gsize len) { |
| 376 struct mwPurplePluginData *pd; | 377 struct mwPurpleProtocolData *pd; |
| 377 gssize ret = 0; | 378 gssize ret = 0; |
| 378 int err = 0; | 379 int err = 0; |
| 379 | 380 |
| 380 pd = mwSession_getClientData(session); | 381 pd = mwSession_getClientData(session); |
| 381 | 382 |
| 429 return 0; | 430 return 0; |
| 430 } | 431 } |
| 431 | 432 |
| 432 | 433 |
| 433 static void mw_session_io_close(struct mwSession *session) { | 434 static void mw_session_io_close(struct mwSession *session) { |
| 434 struct mwPurplePluginData *pd; | 435 struct mwPurpleProtocolData *pd; |
| 435 | 436 |
| 436 pd = mwSession_getClientData(session); | 437 pd = mwSession_getClientData(session); |
| 437 g_return_if_fail(pd != NULL); | 438 g_return_if_fail(pd != NULL); |
| 438 | 439 |
| 439 if(pd->outpa) { | 440 if(pd->outpa) { |
| 485 struct mwAwareSnapshot *aware) { | 486 struct mwAwareSnapshot *aware) { |
| 486 | 487 |
| 487 PurpleConnection *gc; | 488 PurpleConnection *gc; |
| 488 PurpleAccount *acct; | 489 PurpleAccount *acct; |
| 489 | 490 |
| 490 struct mwPurplePluginData *pd; | 491 struct mwPurpleProtocolData *pd; |
| 491 guint32 idle; | 492 guint32 idle; |
| 492 guint stat; | 493 guint stat; |
| 493 const char *id; | 494 const char *id; |
| 494 const char *status = MW_STATE_ACTIVE; | 495 const char *status = MW_STATE_ACTIVE; |
| 495 | 496 |
| 622 | 623 |
| 623 | 624 |
| 624 /** Ensures that an Aware List is associated with the given group, and | 625 /** Ensures that an Aware List is associated with the given group, and |
| 625 returns that list. */ | 626 returns that list. */ |
| 626 static struct mwAwareList * | 627 static struct mwAwareList * |
| 627 list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group) { | 628 list_ensure(struct mwPurpleProtocolData *pd, PurpleGroup *group) { |
| 628 | 629 |
| 629 struct mwAwareList *list; | 630 struct mwAwareList *list; |
| 630 | 631 |
| 631 g_return_val_if_fail(pd != NULL, NULL); | 632 g_return_val_if_fail(pd != NULL, NULL); |
| 632 g_return_val_if_fail(group != NULL, NULL); | 633 g_return_val_if_fail(group != NULL, NULL); |
| 739 } | 740 } |
| 740 } | 741 } |
| 741 } | 742 } |
| 742 | 743 |
| 743 | 744 |
| 744 static void blist_store(struct mwPurplePluginData *pd) { | 745 static void blist_store(struct mwPurpleProtocolData *pd) { |
| 745 | 746 |
| 746 struct mwSametimeList *stlist; | 747 struct mwSametimeList *stlist; |
| 747 struct mwServiceStorage *srvc; | 748 struct mwServiceStorage *srvc; |
| 748 struct mwStorageUnit *unit; | 749 struct mwStorageUnit *unit; |
| 749 | 750 |
| 792 mwServiceStorage_save(srvc, unit, NULL, NULL, NULL); | 793 mwServiceStorage_save(srvc, unit, NULL, NULL, NULL); |
| 793 } | 794 } |
| 794 | 795 |
| 795 | 796 |
| 796 static gboolean blist_save_cb(gpointer data) { | 797 static gboolean blist_save_cb(gpointer data) { |
| 797 struct mwPurplePluginData *pd = data; | 798 struct mwPurpleProtocolData *pd = data; |
| 798 | 799 |
| 799 blist_store(pd); | 800 blist_store(pd); |
| 800 pd->save_event = 0; | 801 pd->save_event = 0; |
| 801 return FALSE; | 802 return FALSE; |
| 802 } | 803 } |
| 803 | 804 |
| 804 | 805 |
| 805 /** schedules the buddy list to be saved to the server */ | 806 /** schedules the buddy list to be saved to the server */ |
| 806 static void blist_schedule(struct mwPurplePluginData *pd) { | 807 static void blist_schedule(struct mwPurpleProtocolData *pd) { |
| 807 if(pd->save_event) return; | 808 if(pd->save_event) return; |
| 808 | 809 |
| 809 pd->save_event = purple_timeout_add_seconds(BLIST_SAVE_SECONDS, | 810 pd->save_event = purple_timeout_add_seconds(BLIST_SAVE_SECONDS, |
| 810 blist_save_cb, pd); | 811 blist_save_cb, pd); |
| 811 } | 812 } |
| 817 } | 818 } |
| 818 | 819 |
| 819 | 820 |
| 820 /** Actually add a buddy to the aware service, and schedule the buddy | 821 /** Actually add a buddy to the aware service, and schedule the buddy |
| 821 list to be saved to the server */ | 822 list to be saved to the server */ |
| 822 static void buddy_add(struct mwPurplePluginData *pd, | 823 static void buddy_add(struct mwPurpleProtocolData *pd, |
| 823 PurpleBuddy *buddy) { | 824 PurpleBuddy *buddy) { |
| 824 | 825 |
| 825 struct mwAwareIdBlock idb = { mwAware_USER, (char *) purple_buddy_get_name(buddy), NULL }; | 826 struct mwAwareIdBlock idb = { mwAware_USER, (char *) purple_buddy_get_name(buddy), NULL }; |
| 826 struct mwAwareList *list; | 827 struct mwAwareList *list; |
| 827 | 828 |
| 846 /** ensure that a PurpleBuddy exists in the group with data | 847 /** ensure that a PurpleBuddy exists in the group with data |
| 847 appropriately matching the st user entry from the st list */ | 848 appropriately matching the st user entry from the st list */ |
| 848 static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group, | 849 static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group, |
| 849 struct mwSametimeUser *stuser) { | 850 struct mwSametimeUser *stuser) { |
| 850 | 851 |
| 851 struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); | 852 struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); |
| 852 PurpleBuddy *buddy; | 853 PurpleBuddy *buddy; |
| 853 PurpleAccount *acct = purple_connection_get_account(gc); | 854 PurpleAccount *acct = purple_connection_get_account(gc); |
| 854 | 855 |
| 855 const char *id = mwSametimeUser_getUser(stuser); | 856 const char *id = mwSametimeUser_getUser(stuser); |
| 856 const char *name = mwSametimeUser_getShortName(stuser); | 857 const char *name = mwSametimeUser_getShortName(stuser); |
| 876 return buddy; | 877 return buddy; |
| 877 } | 878 } |
| 878 | 879 |
| 879 | 880 |
| 880 /** add aware watch for a dynamic group */ | 881 /** add aware watch for a dynamic group */ |
| 881 static void group_add(struct mwPurplePluginData *pd, | 882 static void group_add(struct mwPurpleProtocolData *pd, |
| 882 PurpleGroup *group) { | 883 PurpleGroup *group) { |
| 883 | 884 |
| 884 struct mwAwareIdBlock idb = { mwAware_GROUP, NULL, NULL }; | 885 struct mwAwareIdBlock idb = { mwAware_GROUP, NULL, NULL }; |
| 885 struct mwAwareList *list; | 886 struct mwAwareList *list; |
| 886 const char *n; | 887 const char *n; |
| 1225 st list */ | 1226 st list */ |
| 1226 static void fetch_blist_cb(struct mwServiceStorage *srvc, | 1227 static void fetch_blist_cb(struct mwServiceStorage *srvc, |
| 1227 guint32 result, struct mwStorageUnit *item, | 1228 guint32 result, struct mwStorageUnit *item, |
| 1228 gpointer data) { | 1229 gpointer data) { |
| 1229 | 1230 |
| 1230 struct mwPurplePluginData *pd = data; | 1231 struct mwPurpleProtocolData *pd = data; |
| 1231 struct mwSametimeList *stlist; | 1232 struct mwSametimeList *stlist; |
| 1232 | 1233 |
| 1233 struct mwGetBuffer *b; | 1234 struct mwGetBuffer *b; |
| 1234 | 1235 |
| 1235 g_return_if_fail(result == ERR_SUCCESS); | 1236 g_return_if_fail(result == ERR_SUCCESS); |
| 1258 } | 1259 } |
| 1259 | 1260 |
| 1260 | 1261 |
| 1261 /** signal triggered when a conversation is opened in Purple */ | 1262 /** signal triggered when a conversation is opened in Purple */ |
| 1262 static void conversation_created_cb(PurpleConversation *g_conv, | 1263 static void conversation_created_cb(PurpleConversation *g_conv, |
| 1263 struct mwPurplePluginData *pd) { | 1264 struct mwPurpleProtocolData *pd) { |
| 1264 | 1265 |
| 1265 /* we need to tell the IM service to negotiate features for the | 1266 /* we need to tell the IM service to negotiate features for the |
| 1266 conversation right away, otherwise it'll wait until the first | 1267 conversation right away, otherwise it'll wait until the first |
| 1267 message is sent before offering NotesBuddy features. Therefore | 1268 message is sent before offering NotesBuddy features. Therefore |
| 1268 whenever Purple creates a conversation, we'll immediately open the | 1269 whenever Purple creates a conversation, we'll immediately open the |
| 1291 mwConversation_open(conv); | 1292 mwConversation_open(conv); |
| 1292 } | 1293 } |
| 1293 | 1294 |
| 1294 | 1295 |
| 1295 static void blist_menu_nab(PurpleBlistNode *node, gpointer data) { | 1296 static void blist_menu_nab(PurpleBlistNode *node, gpointer data) { |
| 1296 struct mwPurplePluginData *pd = data; | 1297 struct mwPurpleProtocolData *pd = data; |
| 1297 PurpleConnection *gc; | 1298 PurpleConnection *gc; |
| 1298 | 1299 |
| 1299 PurpleGroup *group = (PurpleGroup *) node; | 1300 PurpleGroup *group = (PurpleGroup *) node; |
| 1300 | 1301 |
| 1301 GString *str; | 1302 GString *str; |
| 1329 | 1330 |
| 1330 /** The normal blist menu prpl function doesn't get called for groups, | 1331 /** The normal blist menu prpl function doesn't get called for groups, |
| 1331 so we use the blist-node-extended-menu signal to trigger this | 1332 so we use the blist-node-extended-menu signal to trigger this |
| 1332 handler */ | 1333 handler */ |
| 1333 static void blist_node_menu_cb(PurpleBlistNode *node, | 1334 static void blist_node_menu_cb(PurpleBlistNode *node, |
| 1334 GList **menu, struct mwPurplePluginData *pd) { | 1335 GList **menu, struct mwPurpleProtocolData *pd) { |
| 1335 const char *owner; | 1336 const char *owner; |
| 1336 PurpleAccount *acct; | 1337 PurpleAccount *acct; |
| 1337 PurpleMenuAction *act; | 1338 PurpleMenuAction *act; |
| 1338 | 1339 |
| 1339 /* we only want groups */ | 1340 /* we only want groups */ |
| 1403 } | 1404 } |
| 1404 } | 1405 } |
| 1405 | 1406 |
| 1406 | 1407 |
| 1407 /** Last thing to happen from a started session */ | 1408 /** Last thing to happen from a started session */ |
| 1408 static void services_starting(struct mwPurplePluginData *pd) { | 1409 static void services_starting(struct mwPurpleProtocolData *pd) { |
| 1409 | 1410 |
| 1410 PurpleConnection *gc; | 1411 PurpleConnection *gc; |
| 1411 PurpleAccount *acct; | 1412 PurpleAccount *acct; |
| 1412 struct mwStorageUnit *unit; | 1413 struct mwStorageUnit *unit; |
| 1413 PurpleBlistNode *l; | 1414 PurpleBlistNode *l; |
| 1455 } | 1456 } |
| 1456 | 1457 |
| 1457 | 1458 |
| 1458 static void session_loginRedirect(struct mwSession *session, | 1459 static void session_loginRedirect(struct mwSession *session, |
| 1459 const char *host) { | 1460 const char *host) { |
| 1460 struct mwPurplePluginData *pd; | 1461 struct mwPurpleProtocolData *pd; |
| 1461 PurpleConnection *gc; | 1462 PurpleConnection *gc; |
| 1462 PurpleAccount *account; | 1463 PurpleAccount *account; |
| 1463 guint port; | 1464 guint port; |
| 1464 const char *current_host; | 1465 const char *current_host; |
| 1465 | 1466 |
| 1487 | 1488 |
| 1488 | 1489 |
| 1489 /** called from mw_session_stateChange when the session's state is | 1490 /** called from mw_session_stateChange when the session's state is |
| 1490 mwSession_STARTED. Any finalizing of start-up stuff should go | 1491 mwSession_STARTED. Any finalizing of start-up stuff should go |
| 1491 here */ | 1492 here */ |
| 1492 static void session_started(struct mwPurplePluginData *pd) { | 1493 static void session_started(struct mwPurpleProtocolData *pd) { |
| 1493 PurpleStatus *status; | 1494 PurpleStatus *status; |
| 1494 PurpleAccount *acct; | 1495 PurpleAccount *acct; |
| 1495 | 1496 |
| 1496 /* set out initial status */ | 1497 /* set out initial status */ |
| 1497 acct = purple_connection_get_account(pd->gc); | 1498 acct = purple_connection_get_account(pd->gc); |
| 1511 /* use our services to do neat things */ | 1512 /* use our services to do neat things */ |
| 1512 services_starting(pd); | 1513 services_starting(pd); |
| 1513 } | 1514 } |
| 1514 | 1515 |
| 1515 | 1516 |
| 1516 static void session_stopping(struct mwPurplePluginData *pd) { | 1517 static void session_stopping(struct mwPurpleProtocolData *pd) { |
| 1517 /* stop watching the signals from session_started */ | 1518 /* stop watching the signals from session_started */ |
| 1518 purple_signals_disconnect_by_handle(pd); | 1519 purple_signals_disconnect_by_handle(pd); |
| 1519 } | 1520 } |
| 1520 | 1521 |
| 1521 | 1522 |
| 1522 static void mw_session_stateChange(struct mwSession *session, | 1523 static void mw_session_stateChange(struct mwSession *session, |
| 1523 enum mwSessionState state, | 1524 enum mwSessionState state, |
| 1524 gpointer info) { | 1525 gpointer info) { |
| 1525 struct mwPurplePluginData *pd; | 1526 struct mwPurpleProtocolData *pd; |
| 1526 PurpleConnection *gc; | 1527 PurpleConnection *gc; |
| 1527 const char *msg = NULL; | 1528 const char *msg = NULL; |
| 1528 | 1529 |
| 1529 pd = mwSession_getClientData(session); | 1530 pd = mwSession_getClientData(session); |
| 1530 gc = pd->gc; | 1531 gc = pd->gc; |
| 1627 } | 1628 } |
| 1628 } | 1629 } |
| 1629 | 1630 |
| 1630 | 1631 |
| 1631 static void mw_session_setPrivacyInfo(struct mwSession *session) { | 1632 static void mw_session_setPrivacyInfo(struct mwSession *session) { |
| 1632 struct mwPurplePluginData *pd; | 1633 struct mwPurpleProtocolData *pd; |
| 1633 PurpleConnection *gc; | 1634 PurpleConnection *gc; |
| 1634 PurpleAccount *acct; | 1635 PurpleAccount *acct; |
| 1635 struct mwPrivacyInfo *privacy; | 1636 struct mwPrivacyInfo *privacy; |
| 1636 GSList *list; | 1637 GSList *list; |
| 1637 guint count; | 1638 guint count; |
| 1673 } | 1674 } |
| 1674 } | 1675 } |
| 1675 | 1676 |
| 1676 | 1677 |
| 1677 static void mw_session_setUserStatus(struct mwSession *session) { | 1678 static void mw_session_setUserStatus(struct mwSession *session) { |
| 1678 struct mwPurplePluginData *pd; | 1679 struct mwPurpleProtocolData *pd; |
| 1679 PurpleConnection *gc; | 1680 PurpleConnection *gc; |
| 1680 struct mwAwareIdBlock idb = { mwAware_USER, NULL, NULL }; | 1681 struct mwAwareIdBlock idb = { mwAware_USER, NULL, NULL }; |
| 1681 struct mwUserStatus *stat; | 1682 struct mwUserStatus *stat; |
| 1682 | 1683 |
| 1683 g_return_if_fail(session != NULL); | 1684 g_return_if_fail(session != NULL); |
| 1741 | 1742 |
| 1742 | 1743 |
| 1743 /** callback triggered from purple_input_add, watches the socked for | 1744 /** callback triggered from purple_input_add, watches the socked for |
| 1744 available data to be processed by the session */ | 1745 available data to be processed by the session */ |
| 1745 static void read_cb(gpointer data, gint source, PurpleInputCondition cond) { | 1746 static void read_cb(gpointer data, gint source, PurpleInputCondition cond) { |
| 1746 struct mwPurplePluginData *pd = data; | 1747 struct mwPurpleProtocolData *pd = data; |
| 1747 int ret = 0, err = 0; | 1748 int ret = 0, err = 0; |
| 1748 | 1749 |
| 1749 g_return_if_fail(pd != NULL); | 1750 g_return_if_fail(pd != NULL); |
| 1750 | 1751 |
| 1751 ret = read_recv(pd->session, pd->socket); | 1752 ret = read_recv(pd->session, pd->socket); |
| 1792 | 1793 |
| 1793 /** Callback passed to purple_proxy_connect when an account is logged | 1794 /** Callback passed to purple_proxy_connect when an account is logged |
| 1794 in, and if the session logging in receives a redirect message */ | 1795 in, and if the session logging in receives a redirect message */ |
| 1795 static void connect_cb(gpointer data, gint source, const gchar *error_message) { | 1796 static void connect_cb(gpointer data, gint source, const gchar *error_message) { |
| 1796 | 1797 |
| 1797 struct mwPurplePluginData *pd = data; | 1798 struct mwPurpleProtocolData *pd = data; |
| 1798 | 1799 |
| 1799 if(source < 0) { | 1800 if(source < 0) { |
| 1800 /* connection failed */ | 1801 /* connection failed */ |
| 1801 | 1802 |
| 1802 if(pd->socket) { | 1803 if(pd->socket) { |
| 1831 | 1832 |
| 1832 static void mw_session_announce(struct mwSession *s, | 1833 static void mw_session_announce(struct mwSession *s, |
| 1833 struct mwLoginInfo *from, | 1834 struct mwLoginInfo *from, |
| 1834 gboolean may_reply, | 1835 gboolean may_reply, |
| 1835 const char *text) { | 1836 const char *text) { |
| 1836 struct mwPurplePluginData *pd; | 1837 struct mwPurpleProtocolData *pd; |
| 1837 PurpleAccount *acct; | 1838 PurpleAccount *acct; |
| 1838 PurpleIMConversation *im; | 1839 PurpleIMConversation *im; |
| 1839 PurpleBuddy *buddy; | 1840 PurpleBuddy *buddy; |
| 1840 char *who = from->user_id; | 1841 char *who = from->user_id; |
| 1841 char *msg; | 1842 char *msg; |
| 1901 struct mwLoginInfo *inviter, | 1902 struct mwLoginInfo *inviter, |
| 1902 const char *invitation) { | 1903 const char *invitation) { |
| 1903 | 1904 |
| 1904 struct mwServiceConference *srvc; | 1905 struct mwServiceConference *srvc; |
| 1905 struct mwSession *session; | 1906 struct mwSession *session; |
| 1906 struct mwPurplePluginData *pd; | 1907 struct mwPurpleProtocolData *pd; |
| 1907 PurpleConnection *gc; | 1908 PurpleConnection *gc; |
| 1908 | 1909 |
| 1909 char *c_inviter, *c_name, *c_topic, *c_invitation; | 1910 char *c_inviter, *c_name, *c_topic, *c_invitation; |
| 1910 GHashTable *ht; | 1911 GHashTable *ht; |
| 1911 | 1912 |
| 1950 #define CHAT_TO_CONF(pd, chat) (ID_TO_CONF((pd), CHAT_TO_ID(chat))) | 1951 #define CHAT_TO_CONF(pd, chat) (ID_TO_CONF((pd), CHAT_TO_ID(chat))) |
| 1951 #define CONF_TO_CHAT(conf) (ID_TO_CHAT(CONF_TO_ID(conf))) | 1952 #define CONF_TO_CHAT(conf) (ID_TO_CHAT(CONF_TO_ID(conf))) |
| 1952 | 1953 |
| 1953 | 1954 |
| 1954 static struct mwConference * | 1955 static struct mwConference * |
| 1955 conf_find_by_id(struct mwPurplePluginData *pd, int id) { | 1956 conf_find_by_id(struct mwPurpleProtocolData *pd, int id) { |
| 1956 | 1957 |
| 1957 struct mwServiceConference *srvc = pd->srvc_conf; | 1958 struct mwServiceConference *srvc = pd->srvc_conf; |
| 1958 struct mwConference *conf = NULL; | 1959 struct mwConference *conf = NULL; |
| 1959 GList *l, *ll; | 1960 GList *l, *ll; |
| 1960 | 1961 |
| 1975 | 1976 |
| 1976 | 1977 |
| 1977 static void mw_conf_opened(struct mwConference *conf, GList *members) { | 1978 static void mw_conf_opened(struct mwConference *conf, GList *members) { |
| 1978 struct mwServiceConference *srvc; | 1979 struct mwServiceConference *srvc; |
| 1979 struct mwSession *session; | 1980 struct mwSession *session; |
| 1980 struct mwPurplePluginData *pd; | 1981 struct mwPurpleProtocolData *pd; |
| 1981 PurpleConnection *gc; | 1982 PurpleConnection *gc; |
| 1982 PurpleChatConversation *g_conf; | 1983 PurpleChatConversation *g_conf; |
| 1983 | 1984 |
| 1984 const char *n = mwConference_getName(conf); | 1985 const char *n = mwConference_getName(conf); |
| 1985 const char *t = mwConference_getTitle(conf); | 1986 const char *t = mwConference_getTitle(conf); |
| 2006 | 2007 |
| 2007 | 2008 |
| 2008 static void mw_conf_closed(struct mwConference *conf, guint32 reason) { | 2009 static void mw_conf_closed(struct mwConference *conf, guint32 reason) { |
| 2009 struct mwServiceConference *srvc; | 2010 struct mwServiceConference *srvc; |
| 2010 struct mwSession *session; | 2011 struct mwSession *session; |
| 2011 struct mwPurplePluginData *pd; | 2012 struct mwPurpleProtocolData *pd; |
| 2012 PurpleConnection *gc; | 2013 PurpleConnection *gc; |
| 2013 | 2014 |
| 2014 const char *n = mwConference_getName(conf); | 2015 const char *n = mwConference_getName(conf); |
| 2015 char *msg = mwError(reason); | 2016 char *msg = mwError(reason); |
| 2016 | 2017 |
| 2064 static void mw_conf_text(struct mwConference *conf, | 2065 static void mw_conf_text(struct mwConference *conf, |
| 2065 struct mwLoginInfo *who, const char *text) { | 2066 struct mwLoginInfo *who, const char *text) { |
| 2066 | 2067 |
| 2067 struct mwServiceConference *srvc; | 2068 struct mwServiceConference *srvc; |
| 2068 struct mwSession *session; | 2069 struct mwSession *session; |
| 2069 struct mwPurplePluginData *pd; | 2070 struct mwPurpleProtocolData *pd; |
| 2070 PurpleConnection *gc; | 2071 PurpleConnection *gc; |
| 2071 char *esc; | 2072 char *esc; |
| 2072 | 2073 |
| 2073 if(! text) return; | 2074 if(! text) return; |
| 2074 | 2075 |
| 2165 - offer it | 2166 - offer it |
| 2166 */ | 2167 */ |
| 2167 | 2168 |
| 2168 struct mwServiceFileTransfer *srvc; | 2169 struct mwServiceFileTransfer *srvc; |
| 2169 struct mwSession *session; | 2170 struct mwSession *session; |
| 2170 struct mwPurplePluginData *pd; | 2171 struct mwPurpleProtocolData *pd; |
| 2171 PurpleConnection *gc; | 2172 PurpleConnection *gc; |
| 2172 PurpleAccount *acct; | 2173 PurpleAccount *acct; |
| 2173 const char *who; | 2174 const char *who; |
| 2174 PurpleXfer *xfer; | 2175 PurpleXfer *xfer; |
| 2175 | 2176 |
| 2410 | 2411 |
| 2411 | 2412 |
| 2412 static PurpleIMConversation *convo_get_im(struct mwConversation *conv) { | 2413 static PurpleIMConversation *convo_get_im(struct mwConversation *conv) { |
| 2413 struct mwServiceIm *srvc; | 2414 struct mwServiceIm *srvc; |
| 2414 struct mwSession *session; | 2415 struct mwSession *session; |
| 2415 struct mwPurplePluginData *pd; | 2416 struct mwPurpleProtocolData *pd; |
| 2416 PurpleConnection *gc; | 2417 PurpleConnection *gc; |
| 2417 PurpleAccount *acct; | 2418 PurpleAccount *acct; |
| 2418 | 2419 |
| 2419 struct mwIdBlock *idb; | 2420 struct mwIdBlock *idb; |
| 2420 | 2421 |
| 2558 | 2559 |
| 2559 | 2560 |
| 2560 static void mw_conversation_opened(struct mwConversation *conv) { | 2561 static void mw_conversation_opened(struct mwConversation *conv) { |
| 2561 struct mwServiceIm *srvc; | 2562 struct mwServiceIm *srvc; |
| 2562 struct mwSession *session; | 2563 struct mwSession *session; |
| 2563 struct mwPurplePluginData *pd; | 2564 struct mwPurpleProtocolData *pd; |
| 2564 PurpleConnection *gc; | 2565 PurpleConnection *gc; |
| 2565 PurpleAccount *acct; | 2566 PurpleAccount *acct; |
| 2566 | 2567 |
| 2567 struct convo_dat *cd; | 2568 struct convo_dat *cd; |
| 2568 | 2569 |
| 2633 mwConversation_removeClientData(conv); | 2634 mwConversation_removeClientData(conv); |
| 2634 } | 2635 } |
| 2635 | 2636 |
| 2636 | 2637 |
| 2637 static void im_recv_text(struct mwConversation *conv, | 2638 static void im_recv_text(struct mwConversation *conv, |
| 2638 struct mwPurplePluginData *pd, | 2639 struct mwPurpleProtocolData *pd, |
| 2639 const char *msg) { | 2640 const char *msg) { |
| 2640 | 2641 |
| 2641 struct mwIdBlock *idb; | 2642 struct mwIdBlock *idb; |
| 2642 char *txt, *esc; | 2643 char *txt, *esc; |
| 2643 const char *t; | 2644 const char *t; |
| 2654 g_free(txt); | 2655 g_free(txt); |
| 2655 } | 2656 } |
| 2656 | 2657 |
| 2657 | 2658 |
| 2658 static void im_recv_typing(struct mwConversation *conv, | 2659 static void im_recv_typing(struct mwConversation *conv, |
| 2659 struct mwPurplePluginData *pd, | 2660 struct mwPurpleProtocolData *pd, |
| 2660 gboolean typing) { | 2661 gboolean typing) { |
| 2661 | 2662 |
| 2662 struct mwIdBlock *idb; | 2663 struct mwIdBlock *idb; |
| 2663 idb = mwConversation_getTarget(conv); | 2664 idb = mwConversation_getTarget(conv); |
| 2664 | 2665 |
| 2666 typing? PURPLE_IM_TYPING: PURPLE_IM_NOT_TYPING); | 2667 typing? PURPLE_IM_TYPING: PURPLE_IM_NOT_TYPING); |
| 2667 } | 2668 } |
| 2668 | 2669 |
| 2669 | 2670 |
| 2670 static void im_recv_html(struct mwConversation *conv, | 2671 static void im_recv_html(struct mwConversation *conv, |
| 2671 struct mwPurplePluginData *pd, | 2672 struct mwPurpleProtocolData *pd, |
| 2672 const char *msg) { | 2673 const char *msg) { |
| 2673 struct mwIdBlock *idb; | 2674 struct mwIdBlock *idb; |
| 2674 char *t1, *t2; | 2675 char *t1, *t2; |
| 2675 const char *t; | 2676 const char *t; |
| 2676 | 2677 |
| 2690 g_free(t2); | 2691 g_free(t2); |
| 2691 } | 2692 } |
| 2692 | 2693 |
| 2693 | 2694 |
| 2694 static void im_recv_subj(struct mwConversation *conv, | 2695 static void im_recv_subj(struct mwConversation *conv, |
| 2695 struct mwPurplePluginData *pd, | 2696 struct mwPurpleProtocolData *pd, |
| 2696 const char *subj) { | 2697 const char *subj) { |
| 2697 | 2698 |
| 2698 /** @todo somehow indicate receipt of a conversation subject. It | 2699 /** @todo somehow indicate receipt of a conversation subject. It |
| 2699 would also be nice if we added a /topic command for the | 2700 would also be nice if we added a /topic command for the |
| 2700 protocol */ | 2701 protocol */ |
| 2719 return d; | 2720 return d; |
| 2720 } | 2721 } |
| 2721 | 2722 |
| 2722 | 2723 |
| 2723 static void im_recv_mime(struct mwConversation *conv, | 2724 static void im_recv_mime(struct mwConversation *conv, |
| 2724 struct mwPurplePluginData *pd, | 2725 struct mwPurpleProtocolData *pd, |
| 2725 const char *data) { | 2726 const char *data) { |
| 2726 | 2727 |
| 2727 GHashTable *img_by_cid; | 2728 GHashTable *img_by_cid; |
| 2728 GList *images; | 2729 GList *images; |
| 2729 | 2730 |
| 2858 static void mw_conversation_recv(struct mwConversation *conv, | 2859 static void mw_conversation_recv(struct mwConversation *conv, |
| 2859 enum mwImSendType type, | 2860 enum mwImSendType type, |
| 2860 gconstpointer msg) { | 2861 gconstpointer msg) { |
| 2861 struct mwServiceIm *srvc; | 2862 struct mwServiceIm *srvc; |
| 2862 struct mwSession *session; | 2863 struct mwSession *session; |
| 2863 struct mwPurplePluginData *pd; | 2864 struct mwPurpleProtocolData *pd; |
| 2864 | 2865 |
| 2865 srvc = mwConversation_getService(conv); | 2866 srvc = mwConversation_getService(conv); |
| 2866 session = mwService_getSession(MW_SERVICE(srvc)); | 2867 session = mwService_getSession(MW_SERVICE(srvc)); |
| 2867 pd = mwSession_getClientData(session); | 2868 pd = mwSession_getClientData(session); |
| 2868 | 2869 |
| 2897 static void mw_place_invite(struct mwConversation *conv, | 2898 static void mw_place_invite(struct mwConversation *conv, |
| 2898 const char *message, | 2899 const char *message, |
| 2899 const char *title, const char *name) { | 2900 const char *title, const char *name) { |
| 2900 struct mwServiceIm *srvc; | 2901 struct mwServiceIm *srvc; |
| 2901 struct mwSession *session; | 2902 struct mwSession *session; |
| 2902 struct mwPurplePluginData *pd; | 2903 struct mwPurpleProtocolData *pd; |
| 2903 | 2904 |
| 2904 struct mwIdBlock *idb; | 2905 struct mwIdBlock *idb; |
| 2905 GHashTable *ht; | 2906 GHashTable *ht; |
| 2906 | 2907 |
| 2907 srvc = mwConversation_getService(conv); | 2908 srvc = mwConversation_getService(conv); |
| 2958 #define CHAT_TO_PLACE(pd, chat) (ID_TO_PLACE((pd), CHAT_TO_ID(chat))) | 2959 #define CHAT_TO_PLACE(pd, chat) (ID_TO_PLACE((pd), CHAT_TO_ID(chat))) |
| 2959 #define PLACE_TO_CHAT(place) (ID_TO_CHAT(PLACE_TO_ID(place))) | 2960 #define PLACE_TO_CHAT(place) (ID_TO_CHAT(PLACE_TO_ID(place))) |
| 2960 | 2961 |
| 2961 | 2962 |
| 2962 static struct mwPlace * | 2963 static struct mwPlace * |
| 2963 place_find_by_id(struct mwPurplePluginData *pd, int id) { | 2964 place_find_by_id(struct mwPurpleProtocolData *pd, int id) { |
| 2964 struct mwServicePlace *srvc = pd->srvc_place; | 2965 struct mwServicePlace *srvc = pd->srvc_place; |
| 2965 struct mwPlace *place = NULL; | 2966 struct mwPlace *place = NULL; |
| 2966 GList *l; | 2967 GList *l; |
| 2967 | 2968 |
| 2968 l = (GList *) mwServicePlace_getPlaces(srvc); | 2969 l = (GList *) mwServicePlace_getPlaces(srvc); |
| 2981 | 2982 |
| 2982 | 2983 |
| 2983 static void mw_place_opened(struct mwPlace *place) { | 2984 static void mw_place_opened(struct mwPlace *place) { |
| 2984 struct mwServicePlace *srvc; | 2985 struct mwServicePlace *srvc; |
| 2985 struct mwSession *session; | 2986 struct mwSession *session; |
| 2986 struct mwPurplePluginData *pd; | 2987 struct mwPurpleProtocolData *pd; |
| 2987 PurpleConnection *gc; | 2988 PurpleConnection *gc; |
| 2988 PurpleChatConversation *gconf; | 2989 PurpleChatConversation *gconf; |
| 2989 | 2990 |
| 2990 GList *members, *l; | 2991 GList *members, *l; |
| 2991 | 2992 |
| 3017 | 3018 |
| 3018 | 3019 |
| 3019 static void mw_place_closed(struct mwPlace *place, guint32 code) { | 3020 static void mw_place_closed(struct mwPlace *place, guint32 code) { |
| 3020 struct mwServicePlace *srvc; | 3021 struct mwServicePlace *srvc; |
| 3021 struct mwSession *session; | 3022 struct mwSession *session; |
| 3022 struct mwPurplePluginData *pd; | 3023 struct mwPurpleProtocolData *pd; |
| 3023 PurpleConnection *gc; | 3024 PurpleConnection *gc; |
| 3024 | 3025 |
| 3025 const char *n = mwPlace_getName(place); | 3026 const char *n = mwPlace_getName(place); |
| 3026 char *msg = mwError(code); | 3027 char *msg = mwError(code); |
| 3027 | 3028 |
| 3087 static void mw_place_message(struct mwPlace *place, | 3088 static void mw_place_message(struct mwPlace *place, |
| 3088 const struct mwIdBlock *who, | 3089 const struct mwIdBlock *who, |
| 3089 const char *msg) { | 3090 const char *msg) { |
| 3090 struct mwServicePlace *srvc; | 3091 struct mwServicePlace *srvc; |
| 3091 struct mwSession *session; | 3092 struct mwSession *session; |
| 3092 struct mwPurplePluginData *pd; | 3093 struct mwPurpleProtocolData *pd; |
| 3093 PurpleConnection *gc; | 3094 PurpleConnection *gc; |
| 3094 char *esc; | 3095 char *esc; |
| 3095 | 3096 |
| 3096 if(! msg) return; | 3097 if(! msg) return; |
| 3097 | 3098 |
| 3142 srvc = mwServiceStorage_new(s); | 3143 srvc = mwServiceStorage_new(s); |
| 3143 return srvc; | 3144 return srvc; |
| 3144 } | 3145 } |
| 3145 | 3146 |
| 3146 | 3147 |
| 3147 /** allocate and associate a mwPurplePluginData with a PurpleConnection */ | 3148 /** allocate and associate a mwPurpleProtocolData with a PurpleConnection */ |
| 3148 static struct mwPurplePluginData *mwPurplePluginData_new(PurpleConnection *gc) { | 3149 static struct mwPurpleProtocolData *mwPurpleProtocolData_new(PurpleConnection *gc) { |
| 3149 struct mwPurplePluginData *pd; | 3150 struct mwPurpleProtocolData *pd; |
| 3150 | 3151 |
| 3151 g_return_val_if_fail(gc != NULL, NULL); | 3152 g_return_val_if_fail(gc != NULL, NULL); |
| 3152 | 3153 |
| 3153 pd = g_new0(struct mwPurplePluginData, 1); | 3154 pd = g_new0(struct mwPurpleProtocolData, 1); |
| 3154 pd->gc = gc; | 3155 pd->gc = gc; |
| 3155 pd->session = mwSession_new(&mw_session_handler); | 3156 pd->session = mwSession_new(&mw_session_handler); |
| 3156 pd->srvc_aware = mw_srvc_aware_new(pd->session); | 3157 pd->srvc_aware = mw_srvc_aware_new(pd->session); |
| 3157 pd->srvc_conf = mw_srvc_conf_new(pd->session); | 3158 pd->srvc_conf = mw_srvc_conf_new(pd->session); |
| 3158 pd->srvc_ft = mw_srvc_ft_new(pd->session); | 3159 pd->srvc_ft = mw_srvc_ft_new(pd->session); |
| 3179 | 3180 |
| 3180 return pd; | 3181 return pd; |
| 3181 } | 3182 } |
| 3182 | 3183 |
| 3183 | 3184 |
| 3184 static void mwPurplePluginData_free(struct mwPurplePluginData *pd) { | 3185 static void mwPurpleProtocolData_free(struct mwPurpleProtocolData *pd) { |
| 3185 g_return_if_fail(pd != NULL); | 3186 g_return_if_fail(pd != NULL); |
| 3186 | 3187 |
| 3187 purple_connection_set_protocol_data(pd->gc, NULL); | 3188 purple_connection_set_protocol_data(pd->gc, NULL); |
| 3188 | 3189 |
| 3189 mwSession_removeService(pd->session, mwService_AWARE); | 3190 mwSession_removeService(pd->session, mwService_AWARE); |
| 3239 } | 3240 } |
| 3240 | 3241 |
| 3241 | 3242 |
| 3242 static char *mw_prpl_status_text(PurpleBuddy *b) { | 3243 static char *mw_prpl_status_text(PurpleBuddy *b) { |
| 3243 PurpleConnection *gc; | 3244 PurpleConnection *gc; |
| 3244 struct mwPurplePluginData *pd; | 3245 struct mwPurpleProtocolData *pd; |
| 3245 struct mwAwareIdBlock t = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL }; | 3246 struct mwAwareIdBlock t = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL }; |
| 3246 const char *ret = NULL; | 3247 const char *ret = NULL; |
| 3247 | 3248 |
| 3248 if ((gc = purple_account_get_connection(purple_buddy_get_account(b))) | 3249 if ((gc = purple_account_get_connection(purple_buddy_get_account(b))) |
| 3249 && (pd = purple_connection_get_protocol_data(gc))) | 3250 && (pd = purple_connection_get_protocol_data(gc))) |
| 3299 } | 3300 } |
| 3300 | 3301 |
| 3301 | 3302 |
| 3302 static void mw_prpl_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { | 3303 static void mw_prpl_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { |
| 3303 PurpleConnection *gc; | 3304 PurpleConnection *gc; |
| 3304 struct mwPurplePluginData *pd = NULL; | 3305 struct mwPurpleProtocolData *pd = NULL; |
| 3305 struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL }; | 3306 struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL }; |
| 3306 | 3307 |
| 3307 const char *message = NULL; | 3308 const char *message = NULL; |
| 3308 const char *status; | 3309 const char *status; |
| 3309 char *tmp; | 3310 char *tmp; |
| 3373 | 3374 |
| 3374 static void conf_create_prompt_join(PurpleBuddy *buddy, | 3375 static void conf_create_prompt_join(PurpleBuddy *buddy, |
| 3375 PurpleRequestFields *fields) { | 3376 PurpleRequestFields *fields) { |
| 3376 PurpleAccount *acct; | 3377 PurpleAccount *acct; |
| 3377 PurpleConnection *gc; | 3378 PurpleConnection *gc; |
| 3378 struct mwPurplePluginData *pd; | 3379 struct mwPurpleProtocolData *pd; |
| 3379 struct mwServiceConference *srvc; | 3380 struct mwServiceConference *srvc; |
| 3380 | 3381 |
| 3381 PurpleRequestField *f; | 3382 PurpleRequestField *f; |
| 3382 | 3383 |
| 3383 const char *topic, *invite; | 3384 const char *topic, *invite; |
| 3538 | 3539 |
| 3539 static void blist_menu_conf(PurpleBlistNode *node, gpointer data) { | 3540 static void blist_menu_conf(PurpleBlistNode *node, gpointer data) { |
| 3540 PurpleBuddy *buddy = (PurpleBuddy *) node; | 3541 PurpleBuddy *buddy = (PurpleBuddy *) node; |
| 3541 PurpleAccount *acct; | 3542 PurpleAccount *acct; |
| 3542 PurpleConnection *gc; | 3543 PurpleConnection *gc; |
| 3543 struct mwPurplePluginData *pd; | 3544 struct mwPurpleProtocolData *pd; |
| 3544 GList *l; | 3545 GList *l; |
| 3545 | 3546 |
| 3546 g_return_if_fail(node != NULL); | 3547 g_return_if_fail(node != NULL); |
| 3547 g_return_if_fail(PURPLE_IS_BUDDY(node)); | 3548 g_return_if_fail(PURPLE_IS_BUDDY(node)); |
| 3548 | 3549 |
| 3575 #if 0 | 3576 #if 0 |
| 3576 static void blist_menu_announce(PurpleBlistNode *node, gpointer data) { | 3577 static void blist_menu_announce(PurpleBlistNode *node, gpointer data) { |
| 3577 PurpleBuddy *buddy = (PurpleBuddy *) node; | 3578 PurpleBuddy *buddy = (PurpleBuddy *) node; |
| 3578 PurpleAccount *acct; | 3579 PurpleAccount *acct; |
| 3579 PurpleConnection *gc; | 3580 PurpleConnection *gc; |
| 3580 struct mwPurplePluginData *pd; | 3581 struct mwPurpleProtocolData *pd; |
| 3581 struct mwSession *session; | 3582 struct mwSession *session; |
| 3582 char *rcpt_name; | 3583 char *rcpt_name; |
| 3583 GList *rcpt; | 3584 GList *rcpt; |
| 3584 | 3585 |
| 3585 g_return_if_fail(node != NULL); | 3586 g_return_if_fail(node != NULL); |
| 3668 static void mw_prpl_login(PurpleAccount *acct); | 3669 static void mw_prpl_login(PurpleAccount *acct); |
| 3669 | 3670 |
| 3670 | 3671 |
| 3671 static void mw_prpl_login(PurpleAccount *account) { | 3672 static void mw_prpl_login(PurpleAccount *account) { |
| 3672 PurpleConnection *gc; | 3673 PurpleConnection *gc; |
| 3673 struct mwPurplePluginData *pd; | 3674 struct mwPurpleProtocolData *pd; |
| 3674 | 3675 |
| 3675 char *user, *pass, *host; | 3676 char *user, *pass, *host; |
| 3676 guint port; | 3677 guint port; |
| 3677 | 3678 |
| 3678 gc = purple_account_get_connection(account); | 3679 gc = purple_account_get_connection(account); |
| 3679 pd = mwPurplePluginData_new(gc); | 3680 pd = mwPurpleProtocolData_new(gc); |
| 3680 | 3681 |
| 3681 /* while we do support images, the default is to not offer it */ | 3682 /* while we do support images, the default is to not offer it */ |
| 3682 purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_IMAGES); | 3683 purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_IMAGES); |
| 3683 | 3684 |
| 3684 user = g_strdup(purple_account_get_username(account)); | 3685 user = g_strdup(purple_account_get_username(account)); |
| 3749 } | 3750 } |
| 3750 } | 3751 } |
| 3751 | 3752 |
| 3752 | 3753 |
| 3753 static void mw_prpl_close(PurpleConnection *gc) { | 3754 static void mw_prpl_close(PurpleConnection *gc) { |
| 3754 struct mwPurplePluginData *pd; | 3755 struct mwPurpleProtocolData *pd; |
| 3755 | 3756 |
| 3756 g_return_if_fail(gc != NULL); | 3757 g_return_if_fail(gc != NULL); |
| 3757 | 3758 |
| 3758 pd = purple_connection_get_protocol_data(gc); | 3759 pd = purple_connection_get_protocol_data(gc); |
| 3759 g_return_if_fail(pd != NULL); | 3760 g_return_if_fail(pd != NULL); |
| 3776 purple_input_remove(pd->inpa); | 3777 purple_input_remove(pd->inpa); |
| 3777 pd->inpa = 0; | 3778 pd->inpa = 0; |
| 3778 } | 3779 } |
| 3779 | 3780 |
| 3780 /* clean up the rest */ | 3781 /* clean up the rest */ |
| 3781 mwPurplePluginData_free(pd); | 3782 mwPurpleProtocolData_free(pd); |
| 3782 } | 3783 } |
| 3783 | 3784 |
| 3784 | 3785 |
| 3785 static int mw_rand(void) { | 3786 static int mw_rand(void) { |
| 3786 static int seed = 0; | 3787 static int seed = 0; |
| 3953 static int mw_prpl_send_im(PurpleConnection *gc, | 3954 static int mw_prpl_send_im(PurpleConnection *gc, |
| 3954 const char *name, | 3955 const char *name, |
| 3955 const char *message, | 3956 const char *message, |
| 3956 PurpleMessageFlags flags) { | 3957 PurpleMessageFlags flags) { |
| 3957 | 3958 |
| 3958 struct mwPurplePluginData *pd; | 3959 struct mwPurpleProtocolData *pd; |
| 3959 struct mwIdBlock who = { (char *) name, NULL }; | 3960 struct mwIdBlock who = { (char *) name, NULL }; |
| 3960 struct mwConversation *conv; | 3961 struct mwConversation *conv; |
| 3961 | 3962 |
| 3962 g_return_val_if_fail(gc != NULL, 0); | 3963 g_return_val_if_fail(gc != NULL, 0); |
| 3963 pd = purple_connection_get_protocol_data(gc); | 3964 pd = purple_connection_get_protocol_data(gc); |
| 4026 | 4027 |
| 4027 static unsigned int mw_prpl_send_typing(PurpleConnection *gc, | 4028 static unsigned int mw_prpl_send_typing(PurpleConnection *gc, |
| 4028 const char *name, | 4029 const char *name, |
| 4029 PurpleIMTypingState state) { | 4030 PurpleIMTypingState state) { |
| 4030 | 4031 |
| 4031 struct mwPurplePluginData *pd; | 4032 struct mwPurpleProtocolData *pd; |
| 4032 struct mwIdBlock who = { (char *) name, NULL }; | 4033 struct mwIdBlock who = { (char *) name, NULL }; |
| 4033 struct mwConversation *conv; | 4034 struct mwConversation *conv; |
| 4034 | 4035 |
| 4035 gpointer t = GINT_TO_POINTER(!! state); | 4036 gpointer t = GINT_TO_POINTER(!! state); |
| 4036 | 4037 |
| 4119 | 4120 |
| 4120 static void mw_prpl_get_info(PurpleConnection *gc, const char *who) { | 4121 static void mw_prpl_get_info(PurpleConnection *gc, const char *who) { |
| 4121 | 4122 |
| 4122 struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL }; | 4123 struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL }; |
| 4123 | 4124 |
| 4124 struct mwPurplePluginData *pd; | 4125 struct mwPurpleProtocolData *pd; |
| 4125 PurpleAccount *acct; | 4126 PurpleAccount *acct; |
| 4126 PurpleBuddy *b; | 4127 PurpleBuddy *b; |
| 4127 PurpleNotifyUserInfo *user_info; | 4128 PurpleNotifyUserInfo *user_info; |
| 4128 char *tmp; | 4129 char *tmp; |
| 4129 const char *tmp2; | 4130 const char *tmp2; |
| 4367 | 4368 |
| 4368 struct mwResolveResult *res = NULL; | 4369 struct mwResolveResult *res = NULL; |
| 4369 BuddyAddData *data = b; | 4370 BuddyAddData *data = b; |
| 4370 PurpleBuddy *buddy = NULL; | 4371 PurpleBuddy *buddy = NULL; |
| 4371 PurpleConnection *gc; | 4372 PurpleConnection *gc; |
| 4372 struct mwPurplePluginData *pd; | 4373 struct mwPurpleProtocolData *pd; |
| 4373 | 4374 |
| 4374 g_return_if_fail(data != NULL); | 4375 g_return_if_fail(data != NULL); |
| 4375 | 4376 |
| 4376 buddy = data->buddy; | 4377 buddy = data->buddy; |
| 4377 | 4378 |
| 4456 static void mw_prpl_add_buddy(PurpleConnection *gc, | 4457 static void mw_prpl_add_buddy(PurpleConnection *gc, |
| 4457 PurpleBuddy *buddy, | 4458 PurpleBuddy *buddy, |
| 4458 PurpleGroup *group, | 4459 PurpleGroup *group, |
| 4459 const char *message) { | 4460 const char *message) { |
| 4460 | 4461 |
| 4461 struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); | 4462 struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); |
| 4462 struct mwServiceResolve *srvc; | 4463 struct mwServiceResolve *srvc; |
| 4463 GList *query; | 4464 GList *query; |
| 4464 enum mwResolveFlag flags; | 4465 enum mwResolveFlag flags; |
| 4465 guint32 req; | 4466 guint32 req; |
| 4466 BuddyAddData *data; | 4467 BuddyAddData *data; |
| 4490 } | 4491 } |
| 4491 } | 4492 } |
| 4492 | 4493 |
| 4493 | 4494 |
| 4494 static void foreach_add_buddies(PurpleGroup *group, GList *buddies, | 4495 static void foreach_add_buddies(PurpleGroup *group, GList *buddies, |
| 4495 struct mwPurplePluginData *pd) { | 4496 struct mwPurpleProtocolData *pd) { |
| 4496 struct mwAwareList *list; | 4497 struct mwAwareList *list; |
| 4497 | 4498 |
| 4498 list = list_ensure(pd, group); | 4499 list = list_ensure(pd, group); |
| 4499 mwAwareList_addAware(list, buddies); | 4500 mwAwareList_addAware(list, buddies); |
| 4500 g_list_free(buddies); | 4501 g_list_free(buddies); |
| 4504 static void mw_prpl_add_buddies(PurpleConnection *gc, | 4505 static void mw_prpl_add_buddies(PurpleConnection *gc, |
| 4505 GList *buddies, | 4506 GList *buddies, |
| 4506 GList *groups, | 4507 GList *groups, |
| 4507 const char *message) { | 4508 const char *message) { |
| 4508 | 4509 |
| 4509 struct mwPurplePluginData *pd; | 4510 struct mwPurpleProtocolData *pd; |
| 4510 GHashTable *group_sets; | 4511 GHashTable *group_sets; |
| 4511 struct mwAwareIdBlock *idbs, *idb; | 4512 struct mwAwareIdBlock *idbs, *idb; |
| 4512 | 4513 |
| 4513 pd = purple_connection_get_protocol_data(gc); | 4514 pd = purple_connection_get_protocol_data(gc); |
| 4514 | 4515 |
| 4553 | 4554 |
| 4554 | 4555 |
| 4555 static void mw_prpl_remove_buddy(PurpleConnection *gc, | 4556 static void mw_prpl_remove_buddy(PurpleConnection *gc, |
| 4556 PurpleBuddy *buddy, PurpleGroup *group) { | 4557 PurpleBuddy *buddy, PurpleGroup *group) { |
| 4557 | 4558 |
| 4558 struct mwPurplePluginData *pd; | 4559 struct mwPurpleProtocolData *pd; |
| 4559 struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(buddy), NULL }; | 4560 struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(buddy), NULL }; |
| 4560 struct mwAwareList *list; | 4561 struct mwAwareList *list; |
| 4561 | 4562 |
| 4562 GList *rem = g_list_prepend(NULL, &idb); | 4563 GList *rem = g_list_prepend(NULL, &idb); |
| 4563 | 4564 |
| 4592 } | 4593 } |
| 4593 | 4594 |
| 4594 | 4595 |
| 4595 static void mw_prpl_set_permit_deny(PurpleConnection *gc) { | 4596 static void mw_prpl_set_permit_deny(PurpleConnection *gc) { |
| 4596 PurpleAccount *acct; | 4597 PurpleAccount *acct; |
| 4597 struct mwPurplePluginData *pd; | 4598 struct mwPurpleProtocolData *pd; |
| 4598 struct mwSession *session; | 4599 struct mwSession *session; |
| 4599 | 4600 |
| 4600 struct mwPrivacyInfo privacy = { | 4601 struct mwPrivacyInfo privacy = { |
| 4601 FALSE, /* deny */ | 4602 FALSE, /* deny */ |
| 4602 0, /* count */ | 4603 0, /* count */ |
| 4687 | 4688 |
| 4688 | 4689 |
| 4689 static void mw_prpl_join_chat(PurpleConnection *gc, | 4690 static void mw_prpl_join_chat(PurpleConnection *gc, |
| 4690 GHashTable *components) { | 4691 GHashTable *components) { |
| 4691 | 4692 |
| 4692 struct mwPurplePluginData *pd; | 4693 struct mwPurpleProtocolData *pd; |
| 4693 char *c, *t; | 4694 char *c, *t; |
| 4694 | 4695 |
| 4695 pd = purple_connection_get_protocol_data(gc); | 4696 pd = purple_connection_get_protocol_data(gc); |
| 4696 | 4697 |
| 4697 c = g_hash_table_lookup(components, CHAT_KEY_NAME); | 4698 c = g_hash_table_lookup(components, CHAT_KEY_NAME); |
| 4728 | 4729 |
| 4729 | 4730 |
| 4730 static void mw_prpl_reject_chat(PurpleConnection *gc, | 4731 static void mw_prpl_reject_chat(PurpleConnection *gc, |
| 4731 GHashTable *components) { | 4732 GHashTable *components) { |
| 4732 | 4733 |
| 4733 struct mwPurplePluginData *pd; | 4734 struct mwPurpleProtocolData *pd; |
| 4734 struct mwServiceConference *srvc; | 4735 struct mwServiceConference *srvc; |
| 4735 char *c; | 4736 char *c; |
| 4736 | 4737 |
| 4737 pd = purple_connection_get_protocol_data(gc); | 4738 pd = purple_connection_get_protocol_data(gc); |
| 4738 srvc = pd->srvc_conf; | 4739 srvc = pd->srvc_conf; |
| 4759 static void mw_prpl_chat_invite(PurpleConnection *gc, | 4760 static void mw_prpl_chat_invite(PurpleConnection *gc, |
| 4760 int id, | 4761 int id, |
| 4761 const char *invitation, | 4762 const char *invitation, |
| 4762 const char *who) { | 4763 const char *who) { |
| 4763 | 4764 |
| 4764 struct mwPurplePluginData *pd; | 4765 struct mwPurpleProtocolData *pd; |
| 4765 struct mwConference *conf; | 4766 struct mwConference *conf; |
| 4766 struct mwPlace *place; | 4767 struct mwPlace *place; |
| 4767 struct mwIdBlock idb = { (char *) who, NULL }; | 4768 struct mwIdBlock idb = { (char *) who, NULL }; |
| 4768 | 4769 |
| 4769 pd = purple_connection_get_protocol_data(gc); | 4770 pd = purple_connection_get_protocol_data(gc); |
| 4785 | 4786 |
| 4786 | 4787 |
| 4787 static void mw_prpl_chat_leave(PurpleConnection *gc, | 4788 static void mw_prpl_chat_leave(PurpleConnection *gc, |
| 4788 int id) { | 4789 int id) { |
| 4789 | 4790 |
| 4790 struct mwPurplePluginData *pd; | 4791 struct mwPurpleProtocolData *pd; |
| 4791 struct mwConference *conf; | 4792 struct mwConference *conf; |
| 4792 | 4793 |
| 4793 pd = purple_connection_get_protocol_data(gc); | 4794 pd = purple_connection_get_protocol_data(gc); |
| 4794 | 4795 |
| 4795 g_return_if_fail(pd != NULL); | 4796 g_return_if_fail(pd != NULL); |
| 4819 static int mw_prpl_chat_send(PurpleConnection *gc, | 4820 static int mw_prpl_chat_send(PurpleConnection *gc, |
| 4820 int id, | 4821 int id, |
| 4821 const char *message, | 4822 const char *message, |
| 4822 PurpleMessageFlags flags) { | 4823 PurpleMessageFlags flags) { |
| 4823 | 4824 |
| 4824 struct mwPurplePluginData *pd; | 4825 struct mwPurpleProtocolData *pd; |
| 4825 struct mwConference *conf; | 4826 struct mwConference *conf; |
| 4826 char *msg; | 4827 char *msg; |
| 4827 int ret; | 4828 int ret; |
| 4828 | 4829 |
| 4829 pd = purple_connection_get_protocol_data(gc); | 4830 pd = purple_connection_get_protocol_data(gc); |
| 4862 | 4863 |
| 4863 static void mw_prpl_alias_buddy(PurpleConnection *gc, | 4864 static void mw_prpl_alias_buddy(PurpleConnection *gc, |
| 4864 const char *who, | 4865 const char *who, |
| 4865 const char *alias) { | 4866 const char *alias) { |
| 4866 | 4867 |
| 4867 struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); | 4868 struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); |
| 4868 g_return_if_fail(pd != NULL); | 4869 g_return_if_fail(pd != NULL); |
| 4869 | 4870 |
| 4870 /* it's a change to the buddy list, so we've gotta reflect that in | 4871 /* it's a change to the buddy list, so we've gotta reflect that in |
| 4871 the server copy */ | 4872 the server copy */ |
| 4872 | 4873 |
| 4880 const char *new_group) { | 4881 const char *new_group) { |
| 4881 | 4882 |
| 4882 struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL }; | 4883 struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL }; |
| 4883 GList *gl = g_list_prepend(NULL, &idb); | 4884 GList *gl = g_list_prepend(NULL, &idb); |
| 4884 | 4885 |
| 4885 struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); | 4886 struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); |
| 4886 PurpleGroup *group; | 4887 PurpleGroup *group; |
| 4887 struct mwAwareList *list; | 4888 struct mwAwareList *list; |
| 4888 | 4889 |
| 4889 /* add who to new_group's aware list */ | 4890 /* add who to new_group's aware list */ |
| 4890 group = purple_blist_find_group(new_group); | 4891 group = purple_blist_find_group(new_group); |
| 4906 static void mw_prpl_rename_group(PurpleConnection *gc, | 4907 static void mw_prpl_rename_group(PurpleConnection *gc, |
| 4907 const char *old, | 4908 const char *old, |
| 4908 PurpleGroup *group, | 4909 PurpleGroup *group, |
| 4909 GList *buddies) { | 4910 GList *buddies) { |
| 4910 | 4911 |
| 4911 struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); | 4912 struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); |
| 4912 g_return_if_fail(pd != NULL); | 4913 g_return_if_fail(pd != NULL); |
| 4913 | 4914 |
| 4914 /* it's a change in the buddy list, so we've gotta reflect that in | 4915 /* it's a change in the buddy list, so we've gotta reflect that in |
| 4915 the server copy. Also, having this function should prevent all | 4916 the server copy. Also, having this function should prevent all |
| 4916 those buddies from being removed and re-added. We don't really | 4917 those buddies from being removed and re-added. We don't really |
| 4926 ; | 4927 ; |
| 4927 } | 4928 } |
| 4928 | 4929 |
| 4929 | 4930 |
| 4930 static void mw_prpl_convo_closed(PurpleConnection *gc, const char *who) { | 4931 static void mw_prpl_convo_closed(PurpleConnection *gc, const char *who) { |
| 4931 struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); | 4932 struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); |
| 4932 struct mwServiceIm *srvc; | 4933 struct mwServiceIm *srvc; |
| 4933 struct mwConversation *conv; | 4934 struct mwConversation *conv; |
| 4934 struct mwIdBlock idb = { (char *) who, NULL }; | 4935 struct mwIdBlock idb = { (char *) who, NULL }; |
| 4935 | 4936 |
| 4936 g_return_if_fail(pd != NULL); | 4937 g_return_if_fail(pd != NULL); |
| 4958 return buf; | 4959 return buf; |
| 4959 } | 4960 } |
| 4960 | 4961 |
| 4961 | 4962 |
| 4962 static void mw_prpl_remove_group(PurpleConnection *gc, PurpleGroup *group) { | 4963 static void mw_prpl_remove_group(PurpleConnection *gc, PurpleGroup *group) { |
| 4963 struct mwPurplePluginData *pd; | 4964 struct mwPurpleProtocolData *pd; |
| 4964 struct mwAwareList *list; | 4965 struct mwAwareList *list; |
| 4965 | 4966 |
| 4966 pd = purple_connection_get_protocol_data(gc); | 4967 pd = purple_connection_get_protocol_data(gc); |
| 4967 g_return_if_fail(pd != NULL); | 4968 g_return_if_fail(pd != NULL); |
| 4968 g_return_if_fail(pd->group_list_map != NULL); | 4969 g_return_if_fail(pd->group_list_map != NULL); |
| 4979 } | 4980 } |
| 4980 | 4981 |
| 4981 | 4982 |
| 4982 static gboolean mw_prpl_can_receive_file(PurpleConnection *gc, | 4983 static gboolean mw_prpl_can_receive_file(PurpleConnection *gc, |
| 4983 const char *who) { | 4984 const char *who) { |
| 4984 struct mwPurplePluginData *pd; | 4985 struct mwPurpleProtocolData *pd; |
| 4985 struct mwServiceAware *srvc; | 4986 struct mwServiceAware *srvc; |
| 4986 PurpleAccount *acct; | 4987 PurpleAccount *acct; |
| 4987 | 4988 |
| 4988 g_return_val_if_fail(gc != NULL, FALSE); | 4989 g_return_val_if_fail(gc != NULL, FALSE); |
| 4989 | 4990 |
| 5003 | 5004 |
| 5004 static void ft_outgoing_init(PurpleXfer *xfer) { | 5005 static void ft_outgoing_init(PurpleXfer *xfer) { |
| 5005 PurpleAccount *acct; | 5006 PurpleAccount *acct; |
| 5006 PurpleConnection *gc; | 5007 PurpleConnection *gc; |
| 5007 | 5008 |
| 5008 struct mwPurplePluginData *pd; | 5009 struct mwPurpleProtocolData *pd; |
| 5009 struct mwServiceFileTransfer *srvc; | 5010 struct mwServiceFileTransfer *srvc; |
| 5010 struct mwFileTransfer *ft; | 5011 struct mwFileTransfer *ft; |
| 5011 | 5012 |
| 5012 const char *filename; | 5013 const char *filename; |
| 5013 gsize filesize; | 5014 gsize filesize; |
| 5098 purple_xfer_request(xfer); | 5099 purple_xfer_request(xfer); |
| 5099 } | 5100 } |
| 5100 } | 5101 } |
| 5101 | 5102 |
| 5102 | 5103 |
| 5104 static PurplePluginPrefFrame * | |
| 5105 mw_plugin_get_plugin_pref_frame(PurplePlugin *plugin) { | |
| 5106 PurplePluginPrefFrame *frame; | |
| 5107 PurplePluginPref *pref; | |
| 5108 | |
| 5109 frame = purple_plugin_pref_frame_new(); | |
| 5110 | |
| 5111 pref = purple_plugin_pref_new_with_label(_("Remotely Stored Buddy List")); | |
| 5112 purple_plugin_pref_frame_add(frame, pref); | |
| 5113 | |
| 5114 | |
| 5115 pref = purple_plugin_pref_new_with_name(MW_PRPL_OPT_BLIST_ACTION); | |
| 5116 purple_plugin_pref_set_label(pref, _("Buddy List Storage Mode")); | |
| 5117 | |
| 5118 purple_plugin_pref_set_type(pref, PURPLE_PLUGIN_PREF_CHOICE); | |
| 5119 purple_plugin_pref_add_choice(pref, _("Local Buddy List Only"), | |
| 5120 GINT_TO_POINTER(blist_choice_LOCAL)); | |
| 5121 purple_plugin_pref_add_choice(pref, _("Merge List from Server"), | |
| 5122 GINT_TO_POINTER(blist_choice_MERGE)); | |
| 5123 purple_plugin_pref_add_choice(pref, _("Merge and Save List to Server"), | |
| 5124 GINT_TO_POINTER(blist_choice_STORE)); | |
| 5125 purple_plugin_pref_add_choice(pref, _("Synchronize List with Server"), | |
| 5126 GINT_TO_POINTER(blist_choice_SYNCH)); | |
| 5127 | |
| 5128 purple_plugin_pref_frame_add(frame, pref); | |
| 5129 | |
| 5130 return frame; | |
| 5131 } | |
| 5132 | |
| 5133 | |
| 5134 static void st_import_action_cb(PurpleConnection *gc, char *filename) { | |
| 5135 struct mwSametimeList *l; | |
| 5136 | |
| 5137 FILE *file; | |
| 5138 char buf[BUF_LEN]; | |
| 5139 size_t len; | |
| 5140 | |
| 5141 GString *str; | |
| 5142 | |
| 5143 file = g_fopen(filename, "r"); | |
| 5144 g_return_if_fail(file != NULL); | |
| 5145 | |
| 5146 str = g_string_new(NULL); | |
| 5147 while( (len = fread(buf, 1, BUF_LEN, file)) ) { | |
| 5148 g_string_append_len(str, buf, len); | |
| 5149 } | |
| 5150 | |
| 5151 fclose(file); | |
| 5152 | |
| 5153 l = mwSametimeList_load(str->str); | |
| 5154 g_string_free(str, TRUE); | |
| 5155 | |
| 5156 blist_merge(gc, l); | |
| 5157 mwSametimeList_free(l); | |
| 5158 } | |
| 5159 | |
| 5160 | |
| 5161 /** prompts for a file to import blist from */ | |
| 5162 static void st_import_action(PurpleProtocolAction *act) { | |
| 5163 PurpleConnection *gc; | |
| 5164 PurpleAccount *account; | |
| 5165 char *title; | |
| 5166 | |
| 5167 gc = act->connection; | |
| 5168 account = purple_connection_get_account(gc); | |
| 5169 title = g_strdup_printf(_("Import Sametime List for Account %s"), | |
| 5170 purple_account_get_username(account)); | |
| 5171 | |
| 5172 purple_request_file(gc, title, NULL, FALSE, | |
| 5173 G_CALLBACK(st_import_action_cb), NULL, | |
| 5174 account, NULL, NULL, | |
| 5175 gc); | |
| 5176 | |
| 5177 g_free(title); | |
| 5178 } | |
| 5179 | |
| 5180 | |
| 5181 static void st_export_action_cb(PurpleConnection *gc, char *filename) { | |
| 5182 struct mwSametimeList *l; | |
| 5183 char *str; | |
| 5184 FILE *file; | |
| 5185 | |
| 5186 file = g_fopen(filename, "w"); | |
| 5187 g_return_if_fail(file != NULL); | |
| 5188 | |
| 5189 l = mwSametimeList_new(); | |
| 5190 blist_export(gc, l); | |
| 5191 str = mwSametimeList_store(l); | |
| 5192 mwSametimeList_free(l); | |
| 5193 | |
| 5194 fprintf(file, "%s", str); | |
| 5195 fclose(file); | |
| 5196 | |
| 5197 g_free(str); | |
| 5198 } | |
| 5199 | |
| 5200 | |
| 5201 /** prompts for a file to export blist to */ | |
| 5202 static void st_export_action(PurpleProtocolAction *act) { | |
| 5203 PurpleConnection *gc; | |
| 5204 PurpleAccount *account; | |
| 5205 char *title; | |
| 5206 | |
| 5207 gc = act->connection; | |
| 5208 account = purple_connection_get_account(gc); | |
| 5209 title = g_strdup_printf(_("Export Sametime List for Account %s"), | |
| 5210 purple_account_get_username(account)); | |
| 5211 | |
| 5212 purple_request_file(gc, title, NULL, TRUE, | |
| 5213 G_CALLBACK(st_export_action_cb), NULL, | |
| 5214 account, NULL, NULL, | |
| 5215 gc); | |
| 5216 | |
| 5217 g_free(title); | |
| 5218 } | |
| 5219 | |
| 5220 | |
| 5221 static void remote_group_multi_cleanup(gpointer ignore, | |
| 5222 PurpleRequestFields *fields) { | |
| 5223 | |
| 5224 PurpleRequestField *f; | |
| 5225 GList *l; | |
| 5226 | |
| 5227 f = purple_request_fields_get_field(fields, "group"); | |
| 5228 l = purple_request_field_list_get_items(f); | |
| 5229 | |
| 5230 for(; l; l = l->next) { | |
| 5231 const char *i = l->data; | |
| 5232 struct named_id *res; | |
| 5233 | |
| 5234 res = purple_request_field_list_get_data(f, i); | |
| 5235 | |
| 5236 g_free(res->id); | |
| 5237 g_free(res->name); | |
| 5238 g_free(res); | |
| 5239 } | |
| 5240 } | |
| 5241 | |
| 5242 | |
| 5243 static void remote_group_done(struct mwPurpleProtocolData *pd, | |
| 5244 const char *id, const char *name) { | |
| 5245 PurpleConnection *gc; | |
| 5246 PurpleAccount *acct; | |
| 5247 PurpleGroup *group; | |
| 5248 PurpleBlistNode *gn; | |
| 5249 const char *owner; | |
| 5250 | |
| 5251 g_return_if_fail(pd != NULL); | |
| 5252 | |
| 5253 gc = pd->gc; | |
| 5254 acct = purple_connection_get_account(gc); | |
| 5255 | |
| 5256 /* collision checking */ | |
| 5257 group = purple_blist_find_group(name); | |
| 5258 if(group) { | |
| 5259 const char *msgA; | |
| 5260 const char *msgB; | |
| 5261 char *msg; | |
| 5262 | |
| 5263 msgA = _("Unable to add group: group exists"); | |
| 5264 msgB = _("A group named '%s' already exists in your buddy list."); | |
| 5265 msg = g_strdup_printf(msgB, name); | |
| 5266 | |
| 5267 purple_notify_error(gc, _("Unable to add group"), msgA, msg); | |
| 5268 | |
| 5269 g_free(msg); | |
| 5270 return; | |
| 5271 } | |
| 5272 | |
| 5273 group = purple_group_new(name); | |
| 5274 gn = (PurpleBlistNode *) group; | |
| 5275 | |
| 5276 owner = purple_account_get_username(acct); | |
| 5277 | |
| 5278 purple_blist_node_set_string(gn, GROUP_KEY_NAME, id); | |
| 5279 purple_blist_node_set_int(gn, GROUP_KEY_TYPE, mwSametimeGroup_DYNAMIC); | |
| 5280 purple_blist_node_set_string(gn, GROUP_KEY_OWNER, owner); | |
| 5281 purple_blist_add_group(group, NULL); | |
| 5282 | |
| 5283 group_add(pd, group); | |
| 5284 blist_schedule(pd); | |
| 5285 } | |
| 5286 | |
| 5287 | |
| 5288 static void remote_group_multi_cb(struct mwPurpleProtocolData *pd, | |
| 5289 PurpleRequestFields *fields) { | |
| 5290 PurpleRequestField *f; | |
| 5291 GList *l; | |
| 5292 | |
| 5293 f = purple_request_fields_get_field(fields, "group"); | |
| 5294 l = purple_request_field_list_get_selected(f); | |
| 5295 | |
| 5296 if(l) { | |
| 5297 const char *i = l->data; | |
| 5298 struct named_id *res; | |
| 5299 | |
| 5300 res = purple_request_field_list_get_data(f, i); | |
| 5301 remote_group_done(pd, res->id, res->name); | |
| 5302 } | |
| 5303 | |
| 5304 remote_group_multi_cleanup(NULL, fields); | |
| 5305 } | |
| 5306 | |
| 5307 | |
| 5308 static void remote_group_multi(struct mwResolveResult *result, | |
| 5309 struct mwPurpleProtocolData *pd) { | |
| 5310 | |
| 5311 PurpleRequestFields *fields; | |
| 5312 PurpleRequestFieldGroup *g; | |
| 5313 PurpleRequestField *f; | |
| 5314 GList *l; | |
| 5315 const char *msgA; | |
| 5316 const char *msgB; | |
| 5317 char *msg; | |
| 5318 | |
| 5319 PurpleConnection *gc = pd->gc; | |
| 5320 | |
| 5321 fields = purple_request_fields_new(); | |
| 5322 | |
| 5323 g = purple_request_field_group_new(NULL); | |
| 5324 purple_request_fields_add_group(fields, g); | |
| 5325 | |
| 5326 f = purple_request_field_list_new("group", _("Possible Matches")); | |
| 5327 purple_request_field_list_set_multi_select(f, FALSE); | |
| 5328 purple_request_field_set_required(f, TRUE); | |
| 5329 | |
| 5330 for(l = result->matches; l; l = l->next) { | |
| 5331 struct mwResolveMatch *match = l->data; | |
| 5332 struct named_id *res = g_new0(struct named_id, 1); | |
| 5333 | |
| 5334 res->id = g_strdup(match->id); | |
| 5335 res->name = g_strdup(match->name); | |
| 5336 | |
| 5337 purple_request_field_list_add_icon(f, res->name, NULL, res); | |
| 5338 } | |
| 5339 | |
| 5340 purple_request_field_group_add_field(g, f); | |
| 5341 | |
| 5342 msgA = _("Notes Address Book group results"); | |
| 5343 msgB = _("The identifier '%s' may possibly refer to any of the following" | |
| 5344 " Notes Address Book groups. Please select the correct group from" | |
| 5345 " the list below to add it to your buddy list."); | |
| 5346 msg = g_strdup_printf(msgB, result->name); | |
| 5347 | |
| 5348 purple_request_fields(gc, _("Select Notes Address Book"), | |
| 5349 msgA, msg, fields, | |
| 5350 _("Add Group"), G_CALLBACK(remote_group_multi_cb), | |
| 5351 _("Cancel"), G_CALLBACK(remote_group_multi_cleanup), | |
| 5352 purple_connection_get_account(gc), result->name, NULL, | |
| 5353 pd); | |
| 5354 | |
| 5355 g_free(msg); | |
| 5356 } | |
| 5357 | |
| 5358 | |
| 5359 static void remote_group_resolved(struct mwServiceResolve *srvc, | |
| 5360 guint32 id, guint32 code, GList *results, | |
| 5361 gpointer b) { | |
| 5362 | |
| 5363 struct mwResolveResult *res = NULL; | |
| 5364 struct mwSession *session; | |
| 5365 struct mwPurpleProtocolData *pd; | |
| 5366 PurpleConnection *gc; | |
| 5367 | |
| 5368 session = mwService_getSession(MW_SERVICE(srvc)); | |
| 5369 g_return_if_fail(session != NULL); | |
| 5370 | |
| 5371 pd = mwSession_getClientData(session); | |
| 5372 g_return_if_fail(pd != NULL); | |
| 5373 | |
| 5374 gc = pd->gc; | |
| 5375 g_return_if_fail(gc != NULL); | |
| 5376 | |
| 5377 if(!code && results) { | |
| 5378 res = results->data; | |
| 5379 | |
| 5380 if(res->matches) { | |
| 5381 remote_group_multi(res, pd); | |
| 5382 return; | |
| 5383 } | |
| 5384 } | |
| 5385 | |
| 5386 if(res && res->name) { | |
| 5387 const char *msgA; | |
| 5388 const char *msgB; | |
| 5389 char *msg; | |
| 5390 | |
| 5391 msgA = _("Unable to add group: group not found"); | |
| 5392 | |
| 5393 msgB = _("The identifier '%s' did not match any Notes Address Book" | |
| 5394 " groups in your Sametime community."); | |
| 5395 msg = g_strdup_printf(msgB, res->name); | |
| 5396 | |
| 5397 purple_notify_error(gc, _("Unable to add group"), msgA, msg); | |
| 5398 | |
| 5399 g_free(msg); | |
| 5400 } | |
| 5401 } | |
| 5402 | |
| 5403 | |
| 5404 static void remote_group_action_cb(PurpleConnection *gc, const char *name) { | |
| 5405 struct mwPurpleProtocolData *pd; | |
| 5406 struct mwServiceResolve *srvc; | |
| 5407 GList *query; | |
| 5408 enum mwResolveFlag flags; | |
| 5409 guint32 req; | |
| 5410 | |
| 5411 pd = purple_connection_get_protocol_data(gc); | |
| 5412 srvc = pd->srvc_resolve; | |
| 5413 | |
| 5414 query = g_list_prepend(NULL, (char *) name); | |
| 5415 flags = mwResolveFlag_FIRST | mwResolveFlag_GROUPS; | |
| 5416 | |
| 5417 req = mwServiceResolve_resolve(srvc, query, flags, remote_group_resolved, | |
| 5418 NULL, NULL); | |
| 5419 g_list_free(query); | |
| 5420 | |
| 5421 if(req == SEARCH_ERROR) { | |
| 5422 /** @todo display error */ | |
| 5423 } | |
| 5424 } | |
| 5425 | |
| 5426 | |
| 5427 static void remote_group_action(PurpleProtocolAction *act) { | |
| 5428 PurpleConnection *gc; | |
| 5429 const char *msgA; | |
| 5430 const char *msgB; | |
| 5431 | |
| 5432 gc = act->connection; | |
| 5433 | |
| 5434 msgA = _("Notes Address Book Group"); | |
| 5435 msgB = _("Enter the name of a Notes Address Book group in the field below" | |
| 5436 " to add the group and its members to your buddy list."); | |
| 5437 | |
| 5438 purple_request_input(gc, _("Add Group"), msgA, msgB, NULL, | |
| 5439 FALSE, FALSE, NULL, | |
| 5440 _("Add"), G_CALLBACK(remote_group_action_cb), | |
| 5441 _("Cancel"), NULL, | |
| 5442 purple_connection_get_account(gc), NULL, NULL, | |
| 5443 gc); | |
| 5444 } | |
| 5445 | |
| 5446 | |
| 5447 static void search_notify(struct mwResolveResult *result, | |
| 5448 PurpleConnection *gc) { | |
| 5449 GList *l; | |
| 5450 const char *msgA; | |
| 5451 const char *msgB; | |
| 5452 char *msg1; | |
| 5453 char *msg2; | |
| 5454 | |
| 5455 PurpleNotifySearchResults *sres; | |
| 5456 PurpleNotifySearchColumn *scol; | |
| 5457 | |
| 5458 sres = purple_notify_searchresults_new(); | |
| 5459 | |
| 5460 scol = purple_notify_searchresults_column_new(_("User Name")); | |
| 5461 purple_notify_searchresults_column_add(sres, scol); | |
| 5462 | |
| 5463 scol = purple_notify_searchresults_column_new(_("Sametime ID")); | |
| 5464 purple_notify_searchresults_column_add(sres, scol); | |
| 5465 | |
| 5466 purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_IM, | |
| 5467 notify_im); | |
| 5468 | |
| 5469 purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_ADD, | |
| 5470 notify_add); | |
| 5471 | |
| 5472 for(l = result->matches; l; l = l->next) { | |
| 5473 struct mwResolveMatch *match = l->data; | |
| 5474 GList *row = NULL; | |
| 5475 | |
| 5476 if(!match->id || !match->name) | |
| 5477 continue; | |
| 5478 | |
| 5479 row = g_list_append(row, g_strdup(match->name)); | |
| 5480 row = g_list_append(row, g_strdup(match->id)); | |
| 5481 purple_notify_searchresults_row_add(sres, row); | |
| 5482 } | |
| 5483 | |
| 5484 msgA = _("Search results for '%s'"); | |
| 5485 msgB = _("The identifier '%s' may possibly refer to any of the following" | |
| 5486 " users. You may add these users to your buddy list or send them" | |
| 5487 " messages with the action buttons below."); | |
| 5488 | |
| 5489 msg1 = g_strdup_printf(msgA, result->name); | |
| 5490 msg2 = g_strdup_printf(msgB, result->name); | |
| 5491 | |
| 5492 purple_notify_searchresults(gc, _("Search Results"), | |
| 5493 msg1, msg2, sres, notify_close, NULL); | |
| 5494 | |
| 5495 g_free(msg1); | |
| 5496 g_free(msg2); | |
| 5497 } | |
| 5498 | |
| 5499 | |
| 5500 static void search_resolved(struct mwServiceResolve *srvc, | |
| 5501 guint32 id, guint32 code, GList *results, | |
| 5502 gpointer b) { | |
| 5503 | |
| 5504 PurpleConnection *gc = b; | |
| 5505 struct mwResolveResult *res = NULL; | |
| 5506 | |
| 5507 if(results) res = results->data; | |
| 5508 | |
| 5509 if(!code && res && res->matches) { | |
| 5510 search_notify(res, gc); | |
| 5511 | |
| 5512 } else { | |
| 5513 const char *msgA; | |
| 5514 const char *msgB; | |
| 5515 char *msg; | |
| 5516 | |
| 5517 msgA = _("No matches"); | |
| 5518 msgB = _("The identifier '%s' did not match any users in your" | |
| 5519 " Sametime community."); | |
| 5520 msg = g_strdup_printf(msgB, (res && res->name) ? NSTR(res->name) : ""); | |
| 5521 | |
| 5522 purple_notify_error(gc, _("No Matches"), msgA, msg); | |
| 5523 | |
| 5524 g_free(msg); | |
| 5525 } | |
| 5526 } | |
| 5527 | |
| 5528 | |
| 5529 static void search_action_cb(PurpleConnection *gc, const char *name) { | |
| 5530 struct mwPurpleProtocolData *pd; | |
| 5531 struct mwServiceResolve *srvc; | |
| 5532 GList *query; | |
| 5533 enum mwResolveFlag flags; | |
| 5534 guint32 req; | |
| 5535 | |
| 5536 pd = purple_connection_get_protocol_data(gc); | |
| 5537 srvc = pd->srvc_resolve; | |
| 5538 | |
| 5539 query = g_list_prepend(NULL, (char *) name); | |
| 5540 flags = mwResolveFlag_FIRST | mwResolveFlag_USERS; | |
| 5541 | |
| 5542 req = mwServiceResolve_resolve(srvc, query, flags, search_resolved, | |
| 5543 gc, NULL); | |
| 5544 g_list_free(query); | |
| 5545 | |
| 5546 if(req == SEARCH_ERROR) { | |
| 5547 /** @todo display error */ | |
| 5548 } | |
| 5549 } | |
| 5550 | |
| 5551 | |
| 5552 static void search_action(PurpleProtocolAction *act) { | |
| 5553 PurpleConnection *gc; | |
| 5554 const char *msgA; | |
| 5555 const char *msgB; | |
| 5556 | |
| 5557 gc = act->connection; | |
| 5558 | |
| 5559 msgA = _("Search for a user"); | |
| 5560 msgB = _("Enter a name or partial ID in the field below to search" | |
| 5561 " for matching users in your Sametime community."); | |
| 5562 | |
| 5563 purple_request_input(gc, _("User Search"), msgA, msgB, NULL, | |
| 5564 FALSE, FALSE, NULL, | |
| 5565 _("Search"), G_CALLBACK(search_action_cb), | |
| 5566 _("Cancel"), NULL, | |
| 5567 purple_connection_get_account(gc), NULL, NULL, | |
| 5568 gc); | |
| 5569 } | |
| 5570 | |
| 5571 | |
| 5572 static GList *mw_prpl_get_actions(PurpleConnection *gc) { | |
| 5573 PurpleProtocolAction *act; | |
| 5574 GList *l = NULL; | |
| 5575 | |
| 5576 act = purple_protocol_action_new(_("Import Sametime List..."), | |
| 5577 st_import_action); | |
| 5578 l = g_list_append(l, act); | |
| 5579 | |
| 5580 act = purple_protocol_action_new(_("Export Sametime List..."), | |
| 5581 st_export_action); | |
| 5582 l = g_list_append(l, act); | |
| 5583 | |
| 5584 act = purple_protocol_action_new(_("Add Notes Address Book Group..."), | |
| 5585 remote_group_action); | |
| 5586 l = g_list_append(l, act); | |
| 5587 | |
| 5588 act = purple_protocol_action_new(_("User Search..."), | |
| 5589 search_action); | |
| 5590 l = g_list_append(l, act); | |
| 5591 | |
| 5592 return l; | |
| 5593 } | |
| 5594 | |
| 5595 | |
| 5596 static void mw_log_handler(const gchar *domain, GLogLevelFlags flags, | |
| 5597 const gchar *msg, gpointer data) { | |
| 5598 | |
| 5599 if(! (msg && *msg)) return; | |
| 5600 | |
| 5601 /* handle g_log requests via purple's built-in debug logging */ | |
| 5602 if(flags & G_LOG_LEVEL_ERROR) { | |
| 5603 purple_debug_error(domain, "%s\n", msg); | |
| 5604 | |
| 5605 } else if(flags & G_LOG_LEVEL_WARNING) { | |
| 5606 purple_debug_warning(domain, "%s\n", msg); | |
| 5607 | |
| 5608 } else { | |
| 5609 purple_debug_info(domain, "%s\n", msg); | |
| 5610 } | |
| 5611 } | |
| 5612 | |
| 5613 | |
| 5103 static PurplePluginProtocolInfo mw_prpl_info = { | 5614 static PurplePluginProtocolInfo mw_prpl_info = { |
| 5615 PLUGIN_ID, | |
| 5616 PLUGIN_NAME, | |
| 5104 sizeof(PurplePluginProtocolInfo), | 5617 sizeof(PurplePluginProtocolInfo), |
| 5105 OPT_PROTO_IM_IMAGE, | 5618 OPT_PROTO_IM_IMAGE, |
| 5106 NULL, /*< set in mw_plugin_init */ | 5619 NULL, /*< set in mw_plugin_init */ |
| 5107 NULL, /*< set in mw_plugin_init */ | 5620 NULL, /*< set in mw_plugin_init */ |
| 5108 NO_BUDDY_ICONS, | 5621 NO_BUDDY_ICONS, |
| 5622 mw_prpl_get_actions, | |
| 5109 mw_prpl_list_icon, | 5623 mw_prpl_list_icon, |
| 5110 mw_prpl_list_emblem, | 5624 mw_prpl_list_emblem, |
| 5111 mw_prpl_status_text, | 5625 mw_prpl_status_text, |
| 5112 mw_prpl_tooltip_text, | 5626 mw_prpl_tooltip_text, |
| 5113 mw_prpl_status_types, | 5627 mw_prpl_status_types, |
| 5173 NULL, | 5687 NULL, |
| 5174 NULL | 5688 NULL |
| 5175 }; | 5689 }; |
| 5176 | 5690 |
| 5177 | 5691 |
| 5178 static PurplePluginPrefFrame * | 5692 static PurplePluginInfo * |
| 5179 mw_plugin_get_plugin_pref_frame(PurplePlugin *plugin) { | 5693 plugin_query(GError **error) |
| 5180 PurplePluginPrefFrame *frame; | 5694 { |
| 5181 PurplePluginPref *pref; | 5695 return purple_plugin_info_new( |
| 5182 | 5696 "id", PLUGIN_ID, |
| 5183 frame = purple_plugin_pref_frame_new(); | 5697 "name", PLUGIN_NAME, |
| 5184 | 5698 "version", DISPLAY_VERSION, |
| 5185 pref = purple_plugin_pref_new_with_label(_("Remotely Stored Buddy List")); | 5699 "category", PLUGIN_CATEGORY, |
| 5186 purple_plugin_pref_frame_add(frame, pref); | 5700 "summary", PLUGIN_SUMMARY, |
| 5187 | 5701 "description", PLUGIN_DESC, |
| 5188 | 5702 "author", PLUGIN_AUTHOR, |
| 5189 pref = purple_plugin_pref_new_with_name(MW_PRPL_OPT_BLIST_ACTION); | 5703 "website", PLUGIN_HOMEPAGE, |
| 5190 purple_plugin_pref_set_label(pref, _("Buddy List Storage Mode")); | 5704 "abi-version", PURPLE_ABI_VERSION, |
| 5191 | 5705 "preferences-frame", mw_plugin_get_plugin_pref_frame, |
| 5192 purple_plugin_pref_set_type(pref, PURPLE_PLUGIN_PREF_CHOICE); | 5706 NULL |
| 5193 purple_plugin_pref_add_choice(pref, _("Local Buddy List Only"), | 5707 ); |
| 5194 GINT_TO_POINTER(blist_choice_LOCAL)); | |
| 5195 purple_plugin_pref_add_choice(pref, _("Merge List from Server"), | |
| 5196 GINT_TO_POINTER(blist_choice_MERGE)); | |
| 5197 purple_plugin_pref_add_choice(pref, _("Merge and Save List to Server"), | |
| 5198 GINT_TO_POINTER(blist_choice_STORE)); | |
| 5199 purple_plugin_pref_add_choice(pref, _("Synchronize List with Server"), | |
| 5200 GINT_TO_POINTER(blist_choice_SYNCH)); | |
| 5201 | |
| 5202 purple_plugin_pref_frame_add(frame, pref); | |
| 5203 | |
| 5204 return frame; | |
| 5205 } | |
| 5206 | |
| 5207 | |
| 5208 static PurplePluginUiInfo mw_plugin_ui_info = { | |
| 5209 mw_plugin_get_plugin_pref_frame, | |
| 5210 0, /* page_num */ | |
| 5211 NULL, /* frame */ | |
| 5212 NULL, | |
| 5213 NULL, | |
| 5214 NULL, | |
| 5215 NULL | |
| 5216 }; | 5708 }; |
| 5217 | 5709 |
| 5218 | 5710 |
| 5219 static void st_import_action_cb(PurpleConnection *gc, char *filename) { | 5711 static gboolean plugin_load(PurplePlugin *plugin, GError **error) { |
| 5220 struct mwSametimeList *l; | |
| 5221 | |
| 5222 FILE *file; | |
| 5223 char buf[BUF_LEN]; | |
| 5224 size_t len; | |
| 5225 | |
| 5226 GString *str; | |
| 5227 | |
| 5228 file = g_fopen(filename, "r"); | |
| 5229 g_return_if_fail(file != NULL); | |
| 5230 | |
| 5231 str = g_string_new(NULL); | |
| 5232 while( (len = fread(buf, 1, BUF_LEN, file)) ) { | |
| 5233 g_string_append_len(str, buf, len); | |
| 5234 } | |
| 5235 | |
| 5236 fclose(file); | |
| 5237 | |
| 5238 l = mwSametimeList_load(str->str); | |
| 5239 g_string_free(str, TRUE); | |
| 5240 | |
| 5241 blist_merge(gc, l); | |
| 5242 mwSametimeList_free(l); | |
| 5243 } | |
| 5244 | |
| 5245 | |
| 5246 /** prompts for a file to import blist from */ | |
| 5247 static void st_import_action(PurplePluginAction *act) { | |
| 5248 PurpleConnection *gc; | |
| 5249 PurpleAccount *account; | |
| 5250 char *title; | |
| 5251 | |
| 5252 gc = act->context; | |
| 5253 account = purple_connection_get_account(gc); | |
| 5254 title = g_strdup_printf(_("Import Sametime List for Account %s"), | |
| 5255 purple_account_get_username(account)); | |
| 5256 | |
| 5257 purple_request_file(gc, title, NULL, FALSE, | |
| 5258 G_CALLBACK(st_import_action_cb), NULL, | |
| 5259 account, NULL, NULL, | |
| 5260 gc); | |
| 5261 | |
| 5262 g_free(title); | |
| 5263 } | |
| 5264 | |
| 5265 | |
| 5266 static void st_export_action_cb(PurpleConnection *gc, char *filename) { | |
| 5267 struct mwSametimeList *l; | |
| 5268 char *str; | |
| 5269 FILE *file; | |
| 5270 | |
| 5271 file = g_fopen(filename, "w"); | |
| 5272 g_return_if_fail(file != NULL); | |
| 5273 | |
| 5274 l = mwSametimeList_new(); | |
| 5275 blist_export(gc, l); | |
| 5276 str = mwSametimeList_store(l); | |
| 5277 mwSametimeList_free(l); | |
| 5278 | |
| 5279 fprintf(file, "%s", str); | |
| 5280 fclose(file); | |
| 5281 | |
| 5282 g_free(str); | |
| 5283 } | |
| 5284 | |
| 5285 | |
| 5286 /** prompts for a file to export blist to */ | |
| 5287 static void st_export_action(PurplePluginAction *act) { | |
| 5288 PurpleConnection *gc; | |
| 5289 PurpleAccount *account; | |
| 5290 char *title; | |
| 5291 | |
| 5292 gc = act->context; | |
| 5293 account = purple_connection_get_account(gc); | |
| 5294 title = g_strdup_printf(_("Export Sametime List for Account %s"), | |
| 5295 purple_account_get_username(account)); | |
| 5296 | |
| 5297 purple_request_file(gc, title, NULL, TRUE, | |
| 5298 G_CALLBACK(st_export_action_cb), NULL, | |
| 5299 account, NULL, NULL, | |
| 5300 gc); | |
| 5301 | |
| 5302 g_free(title); | |
| 5303 } | |
| 5304 | |
| 5305 | |
| 5306 static void remote_group_multi_cleanup(gpointer ignore, | |
| 5307 PurpleRequestFields *fields) { | |
| 5308 | |
| 5309 PurpleRequestField *f; | |
| 5310 GList *l; | |
| 5311 | |
| 5312 f = purple_request_fields_get_field(fields, "group"); | |
| 5313 l = purple_request_field_list_get_items(f); | |
| 5314 | |
| 5315 for(; l; l = l->next) { | |
| 5316 const char *i = l->data; | |
| 5317 struct named_id *res; | |
| 5318 | |
| 5319 res = purple_request_field_list_get_data(f, i); | |
| 5320 | |
| 5321 g_free(res->id); | |
| 5322 g_free(res->name); | |
| 5323 g_free(res); | |
| 5324 } | |
| 5325 } | |
| 5326 | |
| 5327 | |
| 5328 static void remote_group_done(struct mwPurplePluginData *pd, | |
| 5329 const char *id, const char *name) { | |
| 5330 PurpleConnection *gc; | |
| 5331 PurpleAccount *acct; | |
| 5332 PurpleGroup *group; | |
| 5333 PurpleBlistNode *gn; | |
| 5334 const char *owner; | |
| 5335 | |
| 5336 g_return_if_fail(pd != NULL); | |
| 5337 | |
| 5338 gc = pd->gc; | |
| 5339 acct = purple_connection_get_account(gc); | |
| 5340 | |
| 5341 /* collision checking */ | |
| 5342 group = purple_blist_find_group(name); | |
| 5343 if(group) { | |
| 5344 const char *msgA; | |
| 5345 const char *msgB; | |
| 5346 char *msg; | |
| 5347 | |
| 5348 msgA = _("Unable to add group: group exists"); | |
| 5349 msgB = _("A group named '%s' already exists in your buddy list."); | |
| 5350 msg = g_strdup_printf(msgB, name); | |
| 5351 | |
| 5352 purple_notify_error(gc, _("Unable to add group"), msgA, msg); | |
| 5353 | |
| 5354 g_free(msg); | |
| 5355 return; | |
| 5356 } | |
| 5357 | |
| 5358 group = purple_group_new(name); | |
| 5359 gn = (PurpleBlistNode *) group; | |
| 5360 | |
| 5361 owner = purple_account_get_username(acct); | |
| 5362 | |
| 5363 purple_blist_node_set_string(gn, GROUP_KEY_NAME, id); | |
| 5364 purple_blist_node_set_int(gn, GROUP_KEY_TYPE, mwSametimeGroup_DYNAMIC); | |
| 5365 purple_blist_node_set_string(gn, GROUP_KEY_OWNER, owner); | |
| 5366 purple_blist_add_group(group, NULL); | |
| 5367 | |
| 5368 group_add(pd, group); | |
| 5369 blist_schedule(pd); | |
| 5370 } | |
| 5371 | |
| 5372 | |
| 5373 static void remote_group_multi_cb(struct mwPurplePluginData *pd, | |
| 5374 PurpleRequestFields *fields) { | |
| 5375 PurpleRequestField *f; | |
| 5376 GList *l; | |
| 5377 | |
| 5378 f = purple_request_fields_get_field(fields, "group"); | |
| 5379 l = purple_request_field_list_get_selected(f); | |
| 5380 | |
| 5381 if(l) { | |
| 5382 const char *i = l->data; | |
| 5383 struct named_id *res; | |
| 5384 | |
| 5385 res = purple_request_field_list_get_data(f, i); | |
| 5386 remote_group_done(pd, res->id, res->name); | |
| 5387 } | |
| 5388 | |
| 5389 remote_group_multi_cleanup(NULL, fields); | |
| 5390 } | |
| 5391 | |
| 5392 | |
| 5393 static void remote_group_multi(struct mwResolveResult *result, | |
| 5394 struct mwPurplePluginData *pd) { | |
| 5395 | |
| 5396 PurpleRequestFields *fields; | |
| 5397 PurpleRequestFieldGroup *g; | |
| 5398 PurpleRequestField *f; | |
| 5399 GList *l; | |
| 5400 const char *msgA; | |
| 5401 const char *msgB; | |
| 5402 char *msg; | |
| 5403 | |
| 5404 PurpleConnection *gc = pd->gc; | |
| 5405 | |
| 5406 fields = purple_request_fields_new(); | |
| 5407 | |
| 5408 g = purple_request_field_group_new(NULL); | |
| 5409 purple_request_fields_add_group(fields, g); | |
| 5410 | |
| 5411 f = purple_request_field_list_new("group", _("Possible Matches")); | |
| 5412 purple_request_field_list_set_multi_select(f, FALSE); | |
| 5413 purple_request_field_set_required(f, TRUE); | |
| 5414 | |
| 5415 for(l = result->matches; l; l = l->next) { | |
| 5416 struct mwResolveMatch *match = l->data; | |
| 5417 struct named_id *res = g_new0(struct named_id, 1); | |
| 5418 | |
| 5419 res->id = g_strdup(match->id); | |
| 5420 res->name = g_strdup(match->name); | |
| 5421 | |
| 5422 purple_request_field_list_add_icon(f, res->name, NULL, res); | |
| 5423 } | |
| 5424 | |
| 5425 purple_request_field_group_add_field(g, f); | |
| 5426 | |
| 5427 msgA = _("Notes Address Book group results"); | |
| 5428 msgB = _("The identifier '%s' may possibly refer to any of the following" | |
| 5429 " Notes Address Book groups. Please select the correct group from" | |
| 5430 " the list below to add it to your buddy list."); | |
| 5431 msg = g_strdup_printf(msgB, result->name); | |
| 5432 | |
| 5433 purple_request_fields(gc, _("Select Notes Address Book"), | |
| 5434 msgA, msg, fields, | |
| 5435 _("Add Group"), G_CALLBACK(remote_group_multi_cb), | |
| 5436 _("Cancel"), G_CALLBACK(remote_group_multi_cleanup), | |
| 5437 purple_connection_get_account(gc), result->name, NULL, | |
| 5438 pd); | |
| 5439 | |
| 5440 g_free(msg); | |
| 5441 } | |
| 5442 | |
| 5443 | |
| 5444 static void remote_group_resolved(struct mwServiceResolve *srvc, | |
| 5445 guint32 id, guint32 code, GList *results, | |
| 5446 gpointer b) { | |
| 5447 | |
| 5448 struct mwResolveResult *res = NULL; | |
| 5449 struct mwSession *session; | |
| 5450 struct mwPurplePluginData *pd; | |
| 5451 PurpleConnection *gc; | |
| 5452 | |
| 5453 session = mwService_getSession(MW_SERVICE(srvc)); | |
| 5454 g_return_if_fail(session != NULL); | |
| 5455 | |
| 5456 pd = mwSession_getClientData(session); | |
| 5457 g_return_if_fail(pd != NULL); | |
| 5458 | |
| 5459 gc = pd->gc; | |
| 5460 g_return_if_fail(gc != NULL); | |
| 5461 | |
| 5462 if(!code && results) { | |
| 5463 res = results->data; | |
| 5464 | |
| 5465 if(res->matches) { | |
| 5466 remote_group_multi(res, pd); | |
| 5467 return; | |
| 5468 } | |
| 5469 } | |
| 5470 | |
| 5471 if(res && res->name) { | |
| 5472 const char *msgA; | |
| 5473 const char *msgB; | |
| 5474 char *msg; | |
| 5475 | |
| 5476 msgA = _("Unable to add group: group not found"); | |
| 5477 | |
| 5478 msgB = _("The identifier '%s' did not match any Notes Address Book" | |
| 5479 " groups in your Sametime community."); | |
| 5480 msg = g_strdup_printf(msgB, res->name); | |
| 5481 | |
| 5482 purple_notify_error(gc, _("Unable to add group"), msgA, msg); | |
| 5483 | |
| 5484 g_free(msg); | |
| 5485 } | |
| 5486 } | |
| 5487 | |
| 5488 | |
| 5489 static void remote_group_action_cb(PurpleConnection *gc, const char *name) { | |
| 5490 struct mwPurplePluginData *pd; | |
| 5491 struct mwServiceResolve *srvc; | |
| 5492 GList *query; | |
| 5493 enum mwResolveFlag flags; | |
| 5494 guint32 req; | |
| 5495 | |
| 5496 pd = purple_connection_get_protocol_data(gc); | |
| 5497 srvc = pd->srvc_resolve; | |
| 5498 | |
| 5499 query = g_list_prepend(NULL, (char *) name); | |
| 5500 flags = mwResolveFlag_FIRST | mwResolveFlag_GROUPS; | |
| 5501 | |
| 5502 req = mwServiceResolve_resolve(srvc, query, flags, remote_group_resolved, | |
| 5503 NULL, NULL); | |
| 5504 g_list_free(query); | |
| 5505 | |
| 5506 if(req == SEARCH_ERROR) { | |
| 5507 /** @todo display error */ | |
| 5508 } | |
| 5509 } | |
| 5510 | |
| 5511 | |
| 5512 static void remote_group_action(PurplePluginAction *act) { | |
| 5513 PurpleConnection *gc; | |
| 5514 const char *msgA; | |
| 5515 const char *msgB; | |
| 5516 | |
| 5517 gc = act->context; | |
| 5518 | |
| 5519 msgA = _("Notes Address Book Group"); | |
| 5520 msgB = _("Enter the name of a Notes Address Book group in the field below" | |
| 5521 " to add the group and its members to your buddy list."); | |
| 5522 | |
| 5523 purple_request_input(gc, _("Add Group"), msgA, msgB, NULL, | |
| 5524 FALSE, FALSE, NULL, | |
| 5525 _("Add"), G_CALLBACK(remote_group_action_cb), | |
| 5526 _("Cancel"), NULL, | |
| 5527 purple_connection_get_account(gc), NULL, NULL, | |
| 5528 gc); | |
| 5529 } | |
| 5530 | |
| 5531 | |
| 5532 static void search_notify(struct mwResolveResult *result, | |
| 5533 PurpleConnection *gc) { | |
| 5534 GList *l; | |
| 5535 const char *msgA; | |
| 5536 const char *msgB; | |
| 5537 char *msg1; | |
| 5538 char *msg2; | |
| 5539 | |
| 5540 PurpleNotifySearchResults *sres; | |
| 5541 PurpleNotifySearchColumn *scol; | |
| 5542 | |
| 5543 sres = purple_notify_searchresults_new(); | |
| 5544 | |
| 5545 scol = purple_notify_searchresults_column_new(_("User Name")); | |
| 5546 purple_notify_searchresults_column_add(sres, scol); | |
| 5547 | |
| 5548 scol = purple_notify_searchresults_column_new(_("Sametime ID")); | |
| 5549 purple_notify_searchresults_column_add(sres, scol); | |
| 5550 | |
| 5551 purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_IM, | |
| 5552 notify_im); | |
| 5553 | |
| 5554 purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_ADD, | |
| 5555 notify_add); | |
| 5556 | |
| 5557 for(l = result->matches; l; l = l->next) { | |
| 5558 struct mwResolveMatch *match = l->data; | |
| 5559 GList *row = NULL; | |
| 5560 | |
| 5561 if(!match->id || !match->name) | |
| 5562 continue; | |
| 5563 | |
| 5564 row = g_list_append(row, g_strdup(match->name)); | |
| 5565 row = g_list_append(row, g_strdup(match->id)); | |
| 5566 purple_notify_searchresults_row_add(sres, row); | |
| 5567 } | |
| 5568 | |
| 5569 msgA = _("Search results for '%s'"); | |
| 5570 msgB = _("The identifier '%s' may possibly refer to any of the following" | |
| 5571 " users. You may add these users to your buddy list or send them" | |
| 5572 " messages with the action buttons below."); | |
| 5573 | |
| 5574 msg1 = g_strdup_printf(msgA, result->name); | |
| 5575 msg2 = g_strdup_printf(msgB, result->name); | |
| 5576 | |
| 5577 purple_notify_searchresults(gc, _("Search Results"), | |
| 5578 msg1, msg2, sres, notify_close, NULL); | |
| 5579 | |
| 5580 g_free(msg1); | |
| 5581 g_free(msg2); | |
| 5582 } | |
| 5583 | |
| 5584 | |
| 5585 static void search_resolved(struct mwServiceResolve *srvc, | |
| 5586 guint32 id, guint32 code, GList *results, | |
| 5587 gpointer b) { | |
| 5588 | |
| 5589 PurpleConnection *gc = b; | |
| 5590 struct mwResolveResult *res = NULL; | |
| 5591 | |
| 5592 if(results) res = results->data; | |
| 5593 | |
| 5594 if(!code && res && res->matches) { | |
| 5595 search_notify(res, gc); | |
| 5596 | |
| 5597 } else { | |
| 5598 const char *msgA; | |
| 5599 const char *msgB; | |
| 5600 char *msg; | |
| 5601 | |
| 5602 msgA = _("No matches"); | |
| 5603 msgB = _("The identifier '%s' did not match any users in your" | |
| 5604 " Sametime community."); | |
| 5605 msg = g_strdup_printf(msgB, (res && res->name) ? NSTR(res->name) : ""); | |
| 5606 | |
| 5607 purple_notify_error(gc, _("No Matches"), msgA, msg); | |
| 5608 | |
| 5609 g_free(msg); | |
| 5610 } | |
| 5611 } | |
| 5612 | |
| 5613 | |
| 5614 static void search_action_cb(PurpleConnection *gc, const char *name) { | |
| 5615 struct mwPurplePluginData *pd; | |
| 5616 struct mwServiceResolve *srvc; | |
| 5617 GList *query; | |
| 5618 enum mwResolveFlag flags; | |
| 5619 guint32 req; | |
| 5620 | |
| 5621 pd = purple_connection_get_protocol_data(gc); | |
| 5622 srvc = pd->srvc_resolve; | |
| 5623 | |
| 5624 query = g_list_prepend(NULL, (char *) name); | |
| 5625 flags = mwResolveFlag_FIRST | mwResolveFlag_USERS; | |
| 5626 | |
| 5627 req = mwServiceResolve_resolve(srvc, query, flags, search_resolved, | |
| 5628 gc, NULL); | |
| 5629 g_list_free(query); | |
| 5630 | |
| 5631 if(req == SEARCH_ERROR) { | |
| 5632 /** @todo display error */ | |
| 5633 } | |
| 5634 } | |
| 5635 | |
| 5636 | |
| 5637 static void search_action(PurplePluginAction *act) { | |
| 5638 PurpleConnection *gc; | |
| 5639 const char *msgA; | |
| 5640 const char *msgB; | |
| 5641 | |
| 5642 gc = act->context; | |
| 5643 | |
| 5644 msgA = _("Search for a user"); | |
| 5645 msgB = _("Enter a name or partial ID in the field below to search" | |
| 5646 " for matching users in your Sametime community."); | |
| 5647 | |
| 5648 purple_request_input(gc, _("User Search"), msgA, msgB, NULL, | |
| 5649 FALSE, FALSE, NULL, | |
| 5650 _("Search"), G_CALLBACK(search_action_cb), | |
| 5651 _("Cancel"), NULL, | |
| 5652 purple_connection_get_account(gc), NULL, NULL, | |
| 5653 gc); | |
| 5654 } | |
| 5655 | |
| 5656 | |
| 5657 static GList *mw_plugin_actions(PurplePlugin *plugin, gpointer context) { | |
| 5658 PurplePluginAction *act; | |
| 5659 GList *l = NULL; | |
| 5660 | |
| 5661 act = purple_plugin_action_new(_("Import Sametime List..."), | |
| 5662 st_import_action); | |
| 5663 l = g_list_append(l, act); | |
| 5664 | |
| 5665 act = purple_plugin_action_new(_("Export Sametime List..."), | |
| 5666 st_export_action); | |
| 5667 l = g_list_append(l, act); | |
| 5668 | |
| 5669 act = purple_plugin_action_new(_("Add Notes Address Book Group..."), | |
| 5670 remote_group_action); | |
| 5671 l = g_list_append(l, act); | |
| 5672 | |
| 5673 act = purple_plugin_action_new(_("User Search..."), | |
| 5674 search_action); | |
| 5675 l = g_list_append(l, act); | |
| 5676 | |
| 5677 return l; | |
| 5678 } | |
| 5679 | |
| 5680 | |
| 5681 static gboolean mw_plugin_load(PurplePlugin *plugin) { | |
| 5682 return TRUE; | |
| 5683 } | |
| 5684 | |
| 5685 | |
| 5686 static gboolean mw_plugin_unload(PurplePlugin *plugin) { | |
| 5687 return TRUE; | |
| 5688 } | |
| 5689 | |
| 5690 | |
| 5691 static void mw_plugin_destroy(PurplePlugin *plugin) { | |
| 5692 g_log_remove_handler(G_LOG_DOMAIN, log_handler[0]); | |
| 5693 g_log_remove_handler("meanwhile", log_handler[1]); | |
| 5694 } | |
| 5695 | |
| 5696 static PurplePluginInfo mw_plugin_info = | |
| 5697 { | |
| 5698 PURPLE_PLUGIN_MAGIC, | |
| 5699 PURPLE_MAJOR_VERSION, | |
| 5700 PURPLE_MINOR_VERSION, | |
| 5701 PURPLE_PLUGIN_PROTOCOL, /**< type */ | |
| 5702 NULL, /**< ui_requirement */ | |
| 5703 0, /**< flags */ | |
| 5704 NULL, /**< dependencies */ | |
| 5705 PURPLE_PRIORITY_DEFAULT, /**< priority */ | |
| 5706 | |
| 5707 PLUGIN_ID, /**< id */ | |
| 5708 PLUGIN_NAME, /**< name */ | |
| 5709 DISPLAY_VERSION, /**< version */ | |
| 5710 PLUGIN_SUMMARY, /**< summary */ | |
| 5711 PLUGIN_DESC, /**< description */ | |
| 5712 PLUGIN_AUTHOR, /**< author */ | |
| 5713 PLUGIN_HOMEPAGE, /**< homepage */ | |
| 5714 | |
| 5715 mw_plugin_load, /**< load */ | |
| 5716 mw_plugin_unload, /**< unload */ | |
| 5717 mw_plugin_destroy, /**< destroy */ | |
| 5718 | |
| 5719 NULL, /**< ui_info */ | |
| 5720 &mw_prpl_info, /**< extra_info */ | |
| 5721 &mw_plugin_ui_info, /**< prefs_info */ | |
| 5722 mw_plugin_actions, | |
| 5723 | |
| 5724 /* padding */ | |
| 5725 NULL, | |
| 5726 NULL, | |
| 5727 NULL, | |
| 5728 NULL | |
| 5729 }; | |
| 5730 | |
| 5731 | |
| 5732 static void mw_log_handler(const gchar *domain, GLogLevelFlags flags, | |
| 5733 const gchar *msg, gpointer data) { | |
| 5734 | |
| 5735 if(! (msg && *msg)) return; | |
| 5736 | |
| 5737 /* handle g_log requests via purple's built-in debug logging */ | |
| 5738 if(flags & G_LOG_LEVEL_ERROR) { | |
| 5739 purple_debug_error(domain, "%s\n", msg); | |
| 5740 | |
| 5741 } else if(flags & G_LOG_LEVEL_WARNING) { | |
| 5742 purple_debug_warning(domain, "%s\n", msg); | |
| 5743 | |
| 5744 } else { | |
| 5745 purple_debug_info(domain, "%s\n", msg); | |
| 5746 } | |
| 5747 } | |
| 5748 | |
| 5749 | |
| 5750 static void mw_plugin_init(PurplePlugin *plugin) { | |
| 5751 PurpleAccountUserSplit *split; | 5712 PurpleAccountUserSplit *split; |
| 5752 PurpleAccountOption *opt; | 5713 PurpleAccountOption *opt; |
| 5753 GList *l = NULL; | 5714 GList *l = NULL; |
| 5754 | 5715 |
| 5755 GLogLevelFlags logflags = | 5716 GLogLevelFlags logflags = |
| 5801 mw_log_handler, NULL); | 5762 mw_log_handler, NULL); |
| 5802 | 5763 |
| 5803 /* redirect meanwhile's logging to purple's */ | 5764 /* redirect meanwhile's logging to purple's */ |
| 5804 log_handler[1] = g_log_set_handler("meanwhile", logflags, | 5765 log_handler[1] = g_log_set_handler("meanwhile", logflags, |
| 5805 mw_log_handler, NULL); | 5766 mw_log_handler, NULL); |
| 5806 } | 5767 |
| 5807 | 5768 purple_protocols_add(&mw_prpl_info); |
| 5808 | 5769 return TRUE; |
| 5809 PURPLE_INIT_PLUGIN(sametime, mw_plugin_init, mw_plugin_info); | 5770 } |
| 5771 | |
| 5772 | |
| 5773 static gboolean plugin_unload(PurplePlugin *plugin, GError **error) { | |
| 5774 g_log_remove_handler(G_LOG_DOMAIN, log_handler[0]); | |
| 5775 g_log_remove_handler("meanwhile", log_handler[1]); | |
| 5776 | |
| 5777 purple_protocols_remove(&mw_prpl_info); | |
| 5778 return TRUE; | |
| 5779 } | |
| 5780 | |
| 5781 | |
| 5782 PURPLE_PLUGIN_INIT(sametime, plugin_query, plugin_load, plugin_unload); | |
| 5810 /* The End. */ | 5783 /* The End. */ |
| 5811 | 5784 |