Mercurial > pidgin
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 * |