comparison libpurple/plugin.c @ 21563:1b174854bb80

merge of '30fcf2f336afb635b62a5c3ed3adb3e1fa1dd2d1' and 'bb60447c0a8c79afca320f4dc689096f4788e7fa'
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sat, 17 Nov 2007 01:55:21 +0000
parents 166b7949be3d
children 14afe5a92fc2
comparison
equal deleted inserted replaced
20755:774f4924e74e 21563:1b174854bb80
56 static GList *loaded_plugins = NULL; 56 static GList *loaded_plugins = NULL;
57 static GList *protocol_plugins = NULL; 57 static GList *protocol_plugins = NULL;
58 #ifdef PURPLE_PLUGINS 58 #ifdef PURPLE_PLUGINS
59 static GList *load_queue = NULL; 59 static GList *load_queue = NULL;
60 static GList *plugin_loaders = NULL; 60 static GList *plugin_loaders = NULL;
61 static GList *plugins_to_disable = NULL;
61 #endif 62 #endif
62 63
63 /*
64 * TODO: I think the intention was to allow multiple load and unload
65 * callback functions. Perhaps using a GList instead of a
66 * pointer to a single function.
67 */
68 static void (*probe_cb)(void *) = NULL; 64 static void (*probe_cb)(void *) = NULL;
69 static void *probe_cb_data = NULL; 65 static void *probe_cb_data = NULL;
70 static void (*load_cb)(PurplePlugin *, void *) = NULL; 66 static void (*load_cb)(PurplePlugin *, void *) = NULL;
71 static void *load_cb_data = NULL; 67 static void *load_cb_data = NULL;
72 static void (*unload_cb)(PurplePlugin *, void *) = NULL; 68 static void (*unload_cb)(PurplePlugin *, void *) = NULL;
252 /* 248 /*
253 * We pass G_MODULE_BIND_LOCAL here to prevent symbols from 249 * We pass G_MODULE_BIND_LOCAL here to prevent symbols from
254 * plugins being added to the global name space. 250 * plugins being added to the global name space.
255 * 251 *
256 * G_MODULE_BIND_LOCAL was added in glib 2.3.3. 252 * G_MODULE_BIND_LOCAL was added in glib 2.3.3.
257 * TODO: I guess there's nothing we can do about that?
258 */ 253 */
259 #if GLIB_CHECK_VERSION(2,3,3) 254 #if GLIB_CHECK_VERSION(2,3,3)
260 plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL); 255 plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL);
261 #else 256 #else
262 plugin->handle = g_module_open(filename, 0); 257 plugin->handle = g_module_open(filename, 0);
623 618
624 loaded_plugins = g_list_insert_sorted(loaded_plugins, plugin, compare_plugins); 619 loaded_plugins = g_list_insert_sorted(loaded_plugins, plugin, compare_plugins);
625 620
626 plugin->loaded = TRUE; 621 plugin->loaded = TRUE;
627 622
628 /* TODO */
629 if (load_cb != NULL) 623 if (load_cb != NULL)
630 load_cb(plugin, load_cb_data); 624 load_cb(plugin, load_cb_data);
631 625
632 purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin); 626 purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin);
633 627
641 gboolean 635 gboolean
642 purple_plugin_unload(PurplePlugin *plugin) 636 purple_plugin_unload(PurplePlugin *plugin)
643 { 637 {
644 #ifdef PURPLE_PLUGINS 638 #ifdef PURPLE_PLUGINS
645 GList *l; 639 GList *l;
640 GList *ll;
646 641
647 g_return_val_if_fail(plugin != NULL, FALSE); 642 g_return_val_if_fail(plugin != NULL, FALSE);
648
649 loaded_plugins = g_list_remove(loaded_plugins, plugin);
650 if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin))
651 protocol_plugins = g_list_remove(protocol_plugins, plugin);
652
653 g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE); 643 g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE);
654 644
655 purple_debug_info("plugins", "Unloading plugin %s\n", plugin->info->name); 645 purple_debug_info("plugins", "Unloading plugin %s\n", plugin->info->name);
656 646
657 /* cancel any pending dialogs the plugin has */
658 purple_request_close_with_handle(plugin);
659 purple_notify_close_with_handle(plugin);
660
661 plugin->loaded = FALSE;
662
663 /* Unload all plugins that depend on this plugin. */ 647 /* Unload all plugins that depend on this plugin. */
664 while ((l = plugin->dependent_plugins) != NULL) 648 for (l = plugin->dependent_plugins; l != NULL; l = ll) {
665 {
666 const char * dep_name = (const char *)l->data; 649 const char * dep_name = (const char *)l->data;
667 PurplePlugin *dep_plugin; 650 PurplePlugin *dep_plugin;
668 651
652 /* Store a pointer to the next element in the list.
653 * This is because we'll be modifying this list in the loop. */
654 ll = l->next;
655
669 dep_plugin = purple_plugins_find_with_id(dep_name); 656 dep_plugin = purple_plugins_find_with_id(dep_name);
670 657
671 if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin)) 658 if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin))
672 { 659 {
673 if (!purple_plugin_unload(dep_plugin)) 660 if (!purple_plugin_unload(dep_plugin))
674 { 661 {
675 char *tmp; 662 g_free(plugin->error);
676 663 plugin->error = g_strdup_printf(_("%s requires %s, but it failed to unload."),
677 tmp = g_strdup_printf(_("The dependent plugin %s failed to unload."), 664 _(plugin->info->name),
678 _(dep_plugin->info->name)); 665 _(dep_plugin->info->name));
679 666 return FALSE;
680 purple_notify_error(NULL, NULL, 667 }
681 _("There were errors unloading the plugin."), tmp); 668 else
682 g_free(tmp); 669 {
670 plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l);
683 } 671 }
684 } 672 }
685 } 673 }
686 674
687 /* Remove this plugin from each dependency's dependent_plugins list. */ 675 /* Remove this plugin from each dependency's dependent_plugins list. */
697 else 685 else
698 purple_debug_error("plugins", "Unable to remove from dependency list for %s\n", dep_name); 686 purple_debug_error("plugins", "Unable to remove from dependency list for %s\n", dep_name);
699 } 687 }
700 688
701 if (plugin->native_plugin) { 689 if (plugin->native_plugin) {
702 if (plugin->info->unload != NULL) 690 if (plugin->info->unload && !plugin->info->unload(plugin))
703 plugin->info->unload(plugin); 691 return FALSE;
704 692
705 if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) { 693 if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) {
706 PurplePluginProtocolInfo *prpl_info; 694 PurplePluginProtocolInfo *prpl_info;
707 GList *l; 695 GList *l;
708 696
722 if (prpl_info->protocol_options != NULL) { 710 if (prpl_info->protocol_options != NULL) {
723 g_list_free(prpl_info->protocol_options); 711 g_list_free(prpl_info->protocol_options);
724 prpl_info->protocol_options = NULL; 712 prpl_info->protocol_options = NULL;
725 } 713 }
726 } 714 }
727 } 715 } else {
728 else {
729 PurplePlugin *loader; 716 PurplePlugin *loader;
730 PurplePluginLoaderInfo *loader_info; 717 PurplePluginLoaderInfo *loader_info;
731 718
732 loader = find_loader_for_plugin(plugin); 719 loader = find_loader_for_plugin(plugin);
733 720
734 if (loader == NULL) 721 if (loader == NULL)
735 return FALSE; 722 return FALSE;
736 723
737 loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); 724 loader_info = PURPLE_PLUGIN_LOADER_INFO(loader);
738 725
739 if (loader_info->unload != NULL) 726 if (loader_info->unload && !loader_info->unload(plugin))
740 loader_info->unload(plugin); 727 return FALSE;
741 } 728 }
729
730 /* cancel any pending dialogs the plugin has */
731 purple_request_close_with_handle(plugin);
732 purple_notify_close_with_handle(plugin);
742 733
743 purple_signals_disconnect_by_handle(plugin); 734 purple_signals_disconnect_by_handle(plugin);
744 purple_plugin_ipc_unregister_all(plugin); 735 purple_plugin_ipc_unregister_all(plugin);
745 736
746 /* TODO */ 737 loaded_plugins = g_list_remove(loaded_plugins, plugin);
738 if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin))
739 protocol_plugins = g_list_remove(protocol_plugins, plugin);
740 plugins_to_disable = g_list_remove(plugins_to_disable, plugin);
741 plugin->loaded = FALSE;
742
743 /* We wouldn't be anywhere near here if the plugin wasn't loaded, so
744 * if plugin->error is set at all, it had to be from a previous
745 * unload failure. It's obviously okay now.
746 */
747 g_free(plugin->error);
748 plugin->error = NULL;
749
747 if (unload_cb != NULL) 750 if (unload_cb != NULL)
748 unload_cb(plugin, unload_cb_data); 751 unload_cb(plugin, unload_cb_data);
749 752
750 purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin); 753 purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin);
751 754
753 756
754 return TRUE; 757 return TRUE;
755 #else 758 #else
756 return TRUE; 759 return TRUE;
757 #endif /* PURPLE_PLUGINS */ 760 #endif /* PURPLE_PLUGINS */
761 }
762
763 void
764 purple_plugin_disable(PurplePlugin *plugin)
765 {
766 #ifdef PURPLE_PLUGINS
767 g_return_if_fail(plugin != NULL);
768
769 if (!g_list_find(plugins_to_disable, plugin))
770 plugins_to_disable = g_list_prepend(plugins_to_disable, plugin);
771 #endif
758 } 772 }
759 773
760 gboolean 774 gboolean
761 purple_plugin_reload(PurplePlugin *plugin) 775 purple_plugin_reload(PurplePlugin *plugin)
762 { 776 {
1220 purple_plugins_save_loaded(const char *key) 1234 purple_plugins_save_loaded(const char *key)
1221 { 1235 {
1222 #ifdef PURPLE_PLUGINS 1236 #ifdef PURPLE_PLUGINS
1223 GList *pl; 1237 GList *pl;
1224 GList *files = NULL; 1238 GList *files = NULL;
1225 PurplePlugin *p;
1226 1239
1227 for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) { 1240 for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) {
1228 p = pl->data; 1241 PurplePlugin *plugin = pl->data;
1229 1242
1230 if (p->info->type != PURPLE_PLUGIN_PROTOCOL && 1243 if (plugin->info->type != PURPLE_PLUGIN_PROTOCOL &&
1231 p->info->type != PURPLE_PLUGIN_LOADER) { 1244 plugin->info->type != PURPLE_PLUGIN_LOADER &&
1232 files = g_list_append(files, p->path); 1245 !g_list_find(plugins_to_disable, plugin)) {
1246 files = g_list_append(files, plugin->path);
1233 } 1247 }
1234 } 1248 }
1235 1249
1236 purple_prefs_set_path_list(key, files); 1250 purple_prefs_set_path_list(key, files);
1237 g_list_free(files); 1251 g_list_free(files);
1389 } 1403 }
1390 } 1404 }
1391 1405
1392 if (probe_cb != NULL) 1406 if (probe_cb != NULL)
1393 probe_cb(probe_cb_data); 1407 probe_cb(probe_cb_data);
1408
1394 #endif /* PURPLE_PLUGINS */ 1409 #endif /* PURPLE_PLUGINS */
1395 } 1410 }
1396 1411
1397 gboolean 1412 gboolean
1398 purple_plugin_register(PurplePlugin *plugin) 1413 purple_plugin_register(PurplePlugin *plugin)
1462 } 1477 }
1463 1478
1464 void 1479 void
1465 purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data) 1480 purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data)
1466 { 1481 {
1467 /* TODO */
1468 probe_cb = func; 1482 probe_cb = func;
1469 probe_cb_data = data; 1483 probe_cb_data = data;
1470 } 1484 }
1471 1485
1472 void 1486 void
1473 purple_plugins_unregister_probe_notify_cb(void (*func)(void *)) 1487 purple_plugins_unregister_probe_notify_cb(void (*func)(void *))
1474 { 1488 {
1475 /* TODO */
1476 probe_cb = NULL; 1489 probe_cb = NULL;
1477 probe_cb_data = NULL; 1490 probe_cb_data = NULL;
1478 } 1491 }
1479 1492
1480 void 1493 void
1481 purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *), 1494 purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *),
1482 void *data) 1495 void *data)
1483 { 1496 {
1484 /* TODO */
1485 load_cb = func; 1497 load_cb = func;
1486 load_cb_data = data; 1498 load_cb_data = data;
1487 } 1499 }
1488 1500
1489 void 1501 void
1490 purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *)) 1502 purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *))
1491 { 1503 {
1492 /* TODO */
1493 load_cb = NULL; 1504 load_cb = NULL;
1494 load_cb_data = NULL; 1505 load_cb_data = NULL;
1495 } 1506 }
1496 1507
1497 void 1508 void
1498 purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *), 1509 purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *),
1499 void *data) 1510 void *data)
1500 { 1511 {
1501 /* TODO */
1502 unload_cb = func; 1512 unload_cb = func;
1503 unload_cb_data = data; 1513 unload_cb_data = data;
1504 } 1514 }
1505 1515
1506 void 1516 void
1507 purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, void *)) 1517 purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, void *))
1508 { 1518 {
1509 /* TODO */
1510 unload_cb = NULL; 1519 unload_cb = NULL;
1511 unload_cb_data = NULL; 1520 unload_cb_data = NULL;
1512 } 1521 }
1513 1522
1514 PurplePlugin * 1523 PurplePlugin *