Mercurial > pidgin.yaz
comparison src/plugin.c @ 12695:0bc110c7ab91
[gaim-migrate @ 15038]
Let's display outdated plugins in the plugins dialog, but grey them out. This way, the user can find out which plugins need to be updated. They will also be able to view the website address so they know where to get a new version.
Inspired by SF Feature Request #1395058 from Daniel Beardsmore (uilleann).
committer: Tailor Script <tailor@pidgin.im>
| author | Richard Laager <rlaager@wiktel.com> |
|---|---|
| date | Tue, 03 Jan 2006 12:03:02 +0000 |
| parents | 70f18c73da9d |
| children | 18e619ed4eaf |
comparison
equal
deleted
inserted
replaced
| 12694:ebed1bbedb04 | 12695:0bc110c7ab91 |
|---|---|
| 26 #include "notify.h" | 26 #include "notify.h" |
| 27 #include "prefs.h" | 27 #include "prefs.h" |
| 28 #include "prpl.h" | 28 #include "prpl.h" |
| 29 #include "request.h" | 29 #include "request.h" |
| 30 #include "signals.h" | 30 #include "signals.h" |
| 31 #include "util.h" | |
| 31 #include "version.h" | 32 #include "version.h" |
| 32 | 33 |
| 33 typedef struct | 34 typedef struct |
| 34 { | 35 { |
| 35 GHashTable *commands; | 36 GHashTable *commands; |
| 213 basename = gaim_plugin_get_basename(filename); | 214 basename = gaim_plugin_get_basename(filename); |
| 214 plugin = gaim_plugins_find_with_basename(basename); | 215 plugin = gaim_plugins_find_with_basename(basename); |
| 215 g_free(basename); | 216 g_free(basename); |
| 216 if (plugin != NULL) | 217 if (plugin != NULL) |
| 217 { | 218 { |
| 218 if (strcmp(filename, plugin->path)) | 219 if (!strcmp(filename, plugin->path)) |
| 219 gaim_debug_info("plugins", "Not loading %s." | 220 return plugin; |
| 221 else if (!gaim_plugin_is_unloadable(plugin)) | |
| 222 { | |
| 223 gaim_debug_info("plugins", "Not loading %s. " | |
| 220 "Another plugin with the same name (%s) has already been loaded.\n", | 224 "Another plugin with the same name (%s) has already been loaded.\n", |
| 221 filename, plugin->path); | 225 filename, plugin->path); |
| 222 return plugin; | 226 return plugin; |
| 227 } | |
| 228 else | |
| 229 { | |
| 230 /* The old plugin was a different file and it was unloadable. | |
| 231 * There's no guarantee that this new file with the same name | |
| 232 * will be loadable, but unless it fails in one of the silent | |
| 233 * ways and the first one didn't, it's not any worse. The user | |
| 234 * will still see a greyed-out plugin, which is what we want. */ | |
| 235 gaim_plugin_destroy(plugin); | |
| 236 } | |
| 223 } | 237 } |
| 224 | 238 |
| 225 plugin = gaim_plugin_new(has_file_extension(filename, G_MODULE_SUFFIX), filename); | 239 plugin = gaim_plugin_new(has_file_extension(filename, G_MODULE_SUFFIX), filename); |
| 226 | 240 |
| 227 if (plugin->native_plugin) { | 241 if (plugin->native_plugin) { |
| 241 plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL); | 255 plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL); |
| 242 #else | 256 #else |
| 243 plugin->handle = g_module_open(filename, 0); | 257 plugin->handle = g_module_open(filename, 0); |
| 244 #endif | 258 #endif |
| 245 | 259 |
| 246 #ifdef _WIN32 | 260 if (plugin->handle == NULL) |
| 247 /* Restore the original error mode */ | 261 { |
| 248 SetErrorMode(old_error_mode); | 262 const char *error = g_module_error(); |
| 263 if (error == NULL) | |
| 264 error = "Unknown error"; | |
| 265 else if (gaim_str_has_prefix(error, filename)) | |
| 266 { | |
| 267 error = error + strlen(filename); | |
| 268 | |
| 269 /* These are just so we don't crash. If we | |
| 270 * got this far, they should always be true. */ | |
| 271 if (*error == ':') | |
| 272 error++; | |
| 273 if (*error == ' ') | |
| 274 error++; | |
| 275 | |
| 276 /* This shouldn't ever be necessary. */ | |
| 277 if (!*error) | |
| 278 error = "Unknown error"; | |
| 279 } | |
| 280 plugin->error = g_strdup(error); | |
| 281 | |
| 282 gaim_debug_error("plugins", "%s is unloadable: %s\n", | |
| 283 plugin->path, plugin->error); | |
| 284 | |
| 285 #if GLIB_CHECK_VERSION(2,3,3) | |
| 286 plugin->handle = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); | |
| 287 #else | |
| 288 plugin->handle = g_module_open(filename, G_MODULE_BIND_LAZY); | |
| 249 #endif | 289 #endif |
| 250 | 290 |
| 251 if (plugin->handle == NULL) | 291 if (plugin->handle == NULL) |
| 252 { | 292 { |
| 253 error = g_module_error(); | 293 gaim_plugin_destroy(plugin); |
| 254 gaim_debug_error("plugins", "%s is unloadable: %s\n", | 294 return NULL; |
| 255 plugin->path, error ? error : "Unknown error."); | 295 } |
| 256 | 296 else |
| 257 gaim_plugin_destroy(plugin); | 297 { |
| 258 | 298 /* We were able to load the plugin with lazy symbol binding. |
| 259 return NULL; | 299 * This means we're missing some symbol. Mark it as |
| 300 * unloadable and keep going so we get the info to display | |
| 301 * to the user so they know to rebuild this plugin. */ | |
| 302 plugin->unloadable = TRUE; | |
| 303 } | |
| 260 } | 304 } |
| 261 | 305 |
| 262 if (!g_module_symbol(plugin->handle, "gaim_init_plugin", | 306 if (!g_module_symbol(plugin->handle, "gaim_init_plugin", |
| 263 &unpunned)) | 307 &unpunned)) |
| 264 { | 308 { |
| 273 gaim_debug_error("plugins", "Error closing module %s: %s\n", | 317 gaim_debug_error("plugins", "Error closing module %s: %s\n", |
| 274 plugin->path, error); | 318 plugin->path, error); |
| 275 plugin->handle = NULL; | 319 plugin->handle = NULL; |
| 276 | 320 |
| 277 gaim_plugin_destroy(plugin); | 321 gaim_plugin_destroy(plugin); |
| 278 | |
| 279 return NULL; | 322 return NULL; |
| 280 } | 323 } |
| 281 gaim_init_plugin = unpunned; | 324 gaim_init_plugin = unpunned; |
| 282 } | 325 } |
| 283 else { | 326 else { |
| 284 loader = find_loader_for_plugin(plugin); | 327 loader = find_loader_for_plugin(plugin); |
| 285 | 328 |
| 286 if (loader == NULL) { | 329 if (loader == NULL) { |
| 287 gaim_plugin_destroy(plugin); | 330 gaim_plugin_destroy(plugin); |
| 288 | |
| 289 return NULL; | 331 return NULL; |
| 290 } | 332 } |
| 291 | 333 |
| 292 gaim_init_plugin = GAIM_PLUGIN_LOADER_INFO(loader)->probe; | 334 gaim_init_plugin = GAIM_PLUGIN_LOADER_INFO(loader)->probe; |
| 293 } | 335 } |
| 294 | 336 |
| 295 plugin->error = NULL; | 337 #ifdef _WIN32 |
| 296 | 338 /* Restore the original error mode */ |
| 297 if (!gaim_init_plugin(plugin) || plugin->info == NULL) { | 339 SetErrorMode(old_error_mode); |
| 340 #endif | |
| 341 | |
| 342 if (!gaim_init_plugin(plugin) || plugin->info == NULL) | |
| 343 { | |
| 298 gaim_plugin_destroy(plugin); | 344 gaim_plugin_destroy(plugin); |
| 299 | |
| 300 return NULL; | 345 return NULL; |
| 301 } | 346 } |
| 302 | 347 |
| 303 if (plugin->info->magic != GAIM_PLUGIN_MAGIC || | 348 if (plugin->info->magic != GAIM_PLUGIN_MAGIC || |
| 304 plugin->info->major_version != GAIM_MAJOR_VERSION || | 349 plugin->info->major_version != GAIM_MAJOR_VERSION || |
| 305 plugin->info->minor_version > GAIM_MINOR_VERSION) | 350 plugin->info->minor_version > GAIM_MINOR_VERSION) |
| 306 { | 351 { |
| 307 gaim_debug_error("plugins", "%s is unloadable: API version mismatch %d.%d.x (need %d.%d.x)\n", | 352 plugin->error = g_strdup_printf("ABI version mismatch %d.%d.x (need %d.%d.x)", |
| 308 plugin->path, plugin->info->major_version, plugin->info->minor_version, | 353 plugin->info->major_version, plugin->info->minor_version, |
| 309 GAIM_MAJOR_VERSION, GAIM_MINOR_VERSION); | 354 GAIM_MAJOR_VERSION, GAIM_MINOR_VERSION); |
| 310 gaim_plugin_destroy(plugin); | 355 gaim_debug_error("plugins", "%s is unloadable: %s\n", plugin->path, plugin->error); |
| 311 return NULL; | 356 plugin->unloadable = TRUE; |
| 357 return plugin; | |
| 312 } | 358 } |
| 313 | 359 |
| 314 /* If plugin is a PRPL, make sure it implements the required functions */ | 360 /* If plugin is a PRPL, make sure it implements the required functions */ |
| 315 if ((plugin->info->type == GAIM_PLUGIN_PROTOCOL) && ( | 361 if ((plugin->info->type == GAIM_PLUGIN_PROTOCOL) && ( |
| 316 (GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon == NULL) || | 362 (GAIM_PLUGIN_PROTOCOL_INFO(plugin)->list_icon == NULL) || |
| 317 (GAIM_PLUGIN_PROTOCOL_INFO(plugin)->login == NULL) || | 363 (GAIM_PLUGIN_PROTOCOL_INFO(plugin)->login == NULL) || |
| 318 (GAIM_PLUGIN_PROTOCOL_INFO(plugin)->close == NULL))) | 364 (GAIM_PLUGIN_PROTOCOL_INFO(plugin)->close == NULL))) |
| 319 { | 365 { |
| 320 gaim_debug_error("plugins", "%s is unloadable: Does not implement all required functions\n", | 366 plugin->error = g_strdup("Does not implement all required functions"); |
| 321 plugin->path); | 367 gaim_debug_error("plugins", "%s is unloadable: %s\n", plugin->path, plugin->error); |
| 322 gaim_plugin_destroy(plugin); | 368 plugin->unloadable = TRUE; |
| 323 return NULL; | 369 return plugin; |
| 324 } | 370 } |
| 325 | 371 |
| 326 return plugin; | 372 return plugin; |
| 327 #else | 373 #else |
| 328 return NULL; | 374 return NULL; |
| 344 #ifdef GAIM_PLUGINS | 390 #ifdef GAIM_PLUGINS |
| 345 GList *dep_list = NULL; | 391 GList *dep_list = NULL; |
| 346 GList *l; | 392 GList *l; |
| 347 | 393 |
| 348 g_return_val_if_fail(plugin != NULL, FALSE); | 394 g_return_val_if_fail(plugin != NULL, FALSE); |
| 349 g_return_val_if_fail(plugin->error == NULL, FALSE); | |
| 350 | 395 |
| 351 if (gaim_plugin_is_loaded(plugin)) | 396 if (gaim_plugin_is_loaded(plugin)) |
| 352 return TRUE; | 397 return TRUE; |
| 398 | |
| 399 if (gaim_plugin_is_unloadable(plugin)) | |
| 400 return FALSE; | |
| 401 | |
| 402 g_return_val_if_fail(plugin->error == NULL, FALSE); | |
| 353 | 403 |
| 354 /* | 404 /* |
| 355 * Go through the list of the plugin's dependencies. | 405 * Go through the list of the plugin's dependencies. |
| 356 * | 406 * |
| 357 * First pass: Make sure all the plugins needed are probed. | 407 * First pass: Make sure all the plugins needed are probed. |
| 653 gaim_plugin_is_loaded(const GaimPlugin *plugin) | 703 gaim_plugin_is_loaded(const GaimPlugin *plugin) |
| 654 { | 704 { |
| 655 g_return_val_if_fail(plugin != NULL, FALSE); | 705 g_return_val_if_fail(plugin != NULL, FALSE); |
| 656 | 706 |
| 657 return plugin->loaded; | 707 return plugin->loaded; |
| 708 } | |
| 709 | |
| 710 gboolean | |
| 711 gaim_plugin_is_unloadable(const GaimPlugin *plugin) | |
| 712 { | |
| 713 g_return_val_if_fail(plugin != NULL, FALSE); | |
| 714 | |
| 715 return plugin->unloadable; | |
| 658 } | 716 } |
| 659 | 717 |
| 660 const gchar * | 718 const gchar * |
| 661 gaim_plugin_get_id(const GaimPlugin *plugin) { | 719 gaim_plugin_get_id(const GaimPlugin *plugin) { |
| 662 g_return_val_if_fail(plugin, NULL); | 720 g_return_val_if_fail(plugin, NULL); |
