libpurple/protocols/sametime/sametime.c

branch
soc.2013.gobjectification.plugins
changeset 36531
6d45c74af198
parent 36414
18a801df193a
child 36532
eaa5f2f9c1d5
equal deleted inserted replaced
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

mercurial