Mercurial > pidgin
annotate src/module.c @ 3752:b32474e522fa
[gaim-migrate @ 3890]
From: "William T. Mahan" <wtm2@duke.edu>
This patch, against CVS HEAD, fixes three bugs in Oscar File Transfer
support. I can split it up further if desired.
* Send a null checksum when initiating a file transfer, which fixes
"files don't match" warnings produced by some versions of WinAIM; add
a compile-time option to actually compute the checksum, which is
slow but necessary when sending to some Mac clients.
* Don't allow sending files to oneself, because it causes all kinds of
subtle problems and it's not useful.
* Don't crash when there is an error writing to the output file when
receiving.
From: "William T. Mahan" <wtm2@duke.edu>
This patch 2 of 3, which applies on top of the first, adds support for
reverse connections for Oscar File Transfer, the lack of which has
been the biggest complaint so far. Reverse connections are used by
newer AIM clients when there is difficulty verifying the IP of the
sender.
From: "William T. Mahan" <wtm2@duke.edu>
This patch 3 of 3, which applies on top of the first 2, removes the
alarm() and sigaction() calls that were added by my original FT patch
to detect transfer timeouts. Besides apparently not working on
Windows, they involved a lot of ugly code to handle a special case.
My new approach is to add destructors that can called when SNACs are
freed; a timeout is detected when a request SNAC is cleaned up before
the transfer is accepted. Although this touches several files, it is
more generic than the old method. I tried to implement this in an
unintrusive manner, so that there is little preformance penalty for
SNACs that do not use destructors.
My first two patches should work fine without this. If there are any
objections to the third patch, I ask that the first two patches be
applied, in which case I will set up a SourceForge page for this one.
committer: Tailor Script <tailor@pidgin.im>
| author | Luke Schierer <lschiere@pidgin.im> |
|---|---|
| date | Sat, 19 Oct 2002 05:22:30 +0000 |
| parents | 988485669631 |
| children | b359aab1c576 |
| rev | line source |
|---|---|
| 2393 | 1 /* |
| 2 * gaim | |
| 3 * | |
| 4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
| 5 * | |
| 6 * This program is free software; you can redistribute it and/or modify | |
| 7 * it under the terms of the GNU General Public License as published by | |
| 8 * the Free Software Foundation; either version 2 of the License, or | |
| 9 * (at your option) any later version. | |
| 10 * | |
| 11 * This program is distributed in the hope that it will be useful, | |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 * GNU General Public License for more details. | |
| 15 * | |
| 16 * You should have received a copy of the GNU General Public License | |
| 17 * along with this program; if not, write to the Free Software | |
| 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 * | |
| 20 * ---------------- | |
| 21 * The Plug-in plug | |
| 22 * | |
| 23 * Plugin support is currently being maintained by Mike Saraf | |
| 24 * msaraf@dwc.edu | |
| 25 * | |
| 26 * Well, I didn't see any work done on it for a while, so I'm going to try | |
| 27 * my hand at it. - Eric warmenhoven@yahoo.com | |
| 28 * | |
| 29 * Mike is my roomate. I can assure you that he's lazy :-P -- Rob rob@marko.net | |
| 30 * | |
| 31 */ | |
| 32 | |
| 33 #ifdef HAVE_CONFIG_H | |
| 34 #include <config.h> | |
| 35 #endif | |
| 36 | |
|
2414
70cb0ce6991a
[gaim-migrate @ 2427]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2405
diff
changeset
|
37 #include "gaim.h" |
| 3572 | 38 #include "prpl.h" |
|
2414
70cb0ce6991a
[gaim-migrate @ 2427]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2405
diff
changeset
|
39 |
| 2393 | 40 #include <string.h> |
| 41 #include <sys/time.h> | |
| 42 | |
| 43 #include <sys/types.h> | |
| 44 #include <sys/stat.h> | |
| 45 | |
| 46 #include <unistd.h> | |
| 47 #include <stdio.h> | |
| 48 #include <stdlib.h> | |
| 49 | |
| 3630 | 50 #ifdef _WIN32 |
| 51 #include "win32dep.h" | |
| 52 #endif | |
| 53 | |
| 2393 | 54 /* ------------------ Global Variables ----------------------- */ |
| 55 | |
| 56 GList *plugins = NULL; | |
| 3551 | 57 GList *probed_plugins = NULL; |
| 2393 | 58 GList *callbacks = NULL; |
| 59 | |
|
2405
6e637ad18494
[gaim-migrate @ 2418]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2393
diff
changeset
|
60 char *last_dir = NULL; |
|
6e637ad18494
[gaim-migrate @ 2418]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2393
diff
changeset
|
61 |
| 2393 | 62 /* --------------- Function Declarations --------------------- */ |
| 63 | |
| 3466 | 64 struct gaim_plugin * load_plugin(const char *); |
| 3551 | 65 #ifdef GAIM_PLUGINS |
| 2393 | 66 void unload_plugin(struct gaim_plugin *p); |
| 67 struct gaim_plugin *reload_plugin(struct gaim_plugin *p); | |
| 68 void gaim_signal_connect(GModule *, enum gaim_event, void *, void *); | |
| 69 void gaim_signal_disconnect(GModule *, enum gaim_event, void *); | |
| 70 void gaim_plugin_unload(GModule *); | |
| 71 | |
| 72 /* --------------- Static Function Declarations ------------- */ | |
| 73 | |
| 74 static void plugin_remove_callbacks(GModule *); | |
| 3551 | 75 #endif |
| 2393 | 76 /* ------------------ Code Below ---------------------------- */ |
| 77 | |
| 3551 | 78 static int is_so_file(char *filename, char *ext) |
| 79 { | |
| 80 int len; | |
| 81 if (!filename) return 0; | |
| 82 if (!filename[0]) return 0; | |
| 83 len = strlen(filename); | |
| 84 len -= strlen(ext); | |
| 85 if (len < 0) return 0; | |
| 86 return (!strncmp(filename + len, ext, strlen(ext))); | |
| 87 } | |
| 88 | |
| 89 void gaim_probe_plugins() { | |
| 90 GDir *dir; | |
| 91 const gchar *file; | |
| 92 gchar *path; | |
|
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
93 /*struct gaim_plugin_description *plugdes;*/ |
| 3551 | 94 struct gaim_plugin *plug; |
| 3630 | 95 char *probedirs[3]; |
| 3565 | 96 int l; |
| 3551 | 97 #if GAIM_PLUGINS |
| 98 char *(*gaim_plugin_init)(GModule *); | |
| 3572 | 99 char *(*gaim_prpl_init)(struct prpl *); |
| 3551 | 100 char *(*cfunc)(); |
| 3572 | 101 struct prpl * new_prpl; |
| 3551 | 102 struct gaim_plugin_description *(*desc)(); |
| 103 GModule *handle; | |
| 104 #endif | |
| 105 | |
| 3630 | 106 probedirs[0] = LIBDIR; |
| 107 probedirs[1] = gaim_user_dir(); | |
| 108 probedirs[2] = 0; | |
| 3551 | 109 |
| 110 for (l=0; probedirs[l]; l++) { | |
| 111 dir = g_dir_open(probedirs[l], 0, NULL); | |
| 112 if (dir) { | |
| 113 while ((file = g_dir_read_name(dir))) { | |
| 114 #ifdef GAIM_PLUGINS | |
|
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
115 if (is_so_file((char*)file, |
| 3630 | 116 #ifndef _WIN32 |
| 117 ".so" | |
| 118 #else | |
| 119 ".dll" | |
| 120 #endif | |
| 121 ) && g_module_supported()) { | |
| 3551 | 122 path = g_build_filename(probedirs[l], file, NULL); |
| 123 handle = g_module_open(path, 0); | |
| 124 if (!handle) { | |
| 125 debug_printf("%s is unloadable: %s\n", file, g_module_error()); | |
| 126 continue; | |
| 127 } | |
| 3572 | 128 if (g_module_symbol(handle, "gaim_prpl_init", (gpointer *)&gaim_prpl_init)) { |
| 129 plug = g_new0(struct gaim_plugin, 1); | |
| 130 g_snprintf(plug->path, sizeof(plug->path), path); | |
| 131 plug->type = plugin; | |
| 132 | |
| 133 new_prpl = g_new0(struct prpl, 1); | |
| 134 new_prpl->plug = plug; | |
| 135 gaim_prpl_init(new_prpl); | |
| 136 if (new_prpl->protocol == PROTO_ICQ || | |
| 137 find_prpl(new_prpl->protocol)) { | |
| 138 /* Nothing to see here--move along, move along */ | |
| 139 unload_protocol(new_prpl); | |
| 140 continue; | |
| 141 } | |
| 142 protocols = g_slist_insert_sorted(protocols, new_prpl, (GCompareFunc)proto_compare); | |
| 143 g_module_close(handle); | |
| 144 continue; | |
| 145 } | |
| 146 | |
| 3551 | 147 if (!g_module_symbol(handle, "gaim_plugin_init", (gpointer *)&gaim_plugin_init)) { |
| 148 debug_printf("%s is unloadable %s\n", file, g_module_error()); | |
| 149 g_module_close(handle); | |
| 150 continue; | |
| 151 } | |
| 152 plug = g_new0(struct gaim_plugin, 1); | |
| 153 g_snprintf(plug->path, sizeof(plug->path), path); | |
| 154 plug->type = plugin; | |
| 155 g_free(path); | |
| 156 if (g_module_symbol(handle, "gaim_plugin_desc", (gpointer *)&desc)) { | |
| 157 memcpy(&(plug->desc), desc(), sizeof(plug->desc)); | |
| 158 } else { | |
| 159 if (g_module_symbol(handle, "name", (gpointer *)&cfunc)) { | |
| 160 plug->desc.name = g_strdup(cfunc()); | |
| 161 } | |
| 162 if (g_module_symbol(handle, "description", (gpointer *)&cfunc)) { | |
| 163 plug->desc.description = g_strdup(cfunc()); | |
| 164 } | |
| 165 } | |
| 166 probed_plugins = g_list_append(probed_plugins, plug); | |
| 167 g_module_close(handle); | |
| 168 } | |
| 169 #endif | |
| 170 #ifdef USE_PERL | |
|
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
171 if (is_so_file((char*)file, ".pl")) { |
| 3563 | 172 path = g_build_filename(probedirs[l], file, NULL); |
| 3551 | 173 plug = probe_perl(path); |
| 174 if (plug) | |
| 175 probed_plugins = g_list_append(probed_plugins, plug); | |
| 176 g_free(path); | |
| 177 } | |
| 178 #endif | |
| 179 } | |
| 180 g_dir_close(dir); | |
| 181 } | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 #ifdef GAIM_PLUGINS | |
| 3466 | 186 struct gaim_plugin *load_plugin(const char *filename) |
| 2393 | 187 { |
|
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
188 struct gaim_plugin *plug=NULL; |
| 3551 | 189 struct gaim_plugin_description *desc; |
| 190 struct gaim_plugin_description *(*gaim_plugin_desc)(); | |
| 2393 | 191 char *(*cfunc)(); |
|
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
192 /*GList *c = plugins;*/ |
| 3551 | 193 GList *p = probed_plugins; |
| 194 char *(*gaim_plugin_init)(GModule *); | |
|
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
195 char *error=NULL; |
|
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
196 char *retval; |
| 3551 | 197 gboolean newplug = FALSE; |
| 2393 | 198 |
| 199 if (!g_module_supported()) | |
| 200 return NULL; | |
| 3551 | 201 if (!filename || !strlen(filename)) |
| 2393 | 202 return NULL; |
| 203 | |
| 3565 | 204 #ifdef USE_PERL |
|
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
205 if (is_so_file((char*)filename, ".pl")) { |
|
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
206 /* perl_load_file is returning an int.. this should be fixed */ |
|
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3630
diff
changeset
|
207 return (struct gaim_plugin *)perl_load_file((char*)filename); |
| 3563 | 208 } |
| 3565 | 209 #endif |
| 3563 | 210 |
| 3551 | 211 while (filename && p) { |
| 212 plug = (struct gaim_plugin *)p->data; | |
| 213 if (!strcmp(filename, plug->path)) | |
| 214 break; | |
| 215 p = p->next; | |
| 2393 | 216 } |
| 3551 | 217 |
| 218 if (plug && plug->handle) { | |
| 219 reload_plugin(plug); | |
| 220 return NULL; | |
| 221 } | |
| 222 | |
| 223 if (!plug) { | |
| 224 plug = g_new0(struct gaim_plugin, 1); | |
| 225 g_snprintf(plug->path, sizeof(plug->path), filename); | |
| 226 newplug = TRUE; | |
| 227 } | |
| 228 | |
| 2393 | 229 debug_printf("Loading %s\n", filename); |
| 230 plug->handle = g_module_open(filename, 0); | |
| 231 if (!plug->handle) { | |
| 232 error = (char *)g_module_error(); | |
| 3551 | 233 plug->handle = NULL; |
| 3563 | 234 g_snprintf(plug->error, sizeof(plug->error), error); |
| 2393 | 235 return NULL; |
| 236 } | |
| 3551 | 237 |
| 2393 | 238 if (!g_module_symbol(plug->handle, "gaim_plugin_init", (gpointer *)&gaim_plugin_init)) { |
| 239 g_module_close(plug->handle); | |
| 3551 | 240 plug->handle = NULL; |
| 3563 | 241 g_snprintf(plug->error, sizeof(plug->error), error); |
| 2393 | 242 return NULL; |
| 243 } | |
| 244 | |
| 3563 | 245 plug->error[0] = '\0'; |
|
2662
b0c5770156e1
[gaim-migrate @ 2675]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2511
diff
changeset
|
246 retval = gaim_plugin_init(plug->handle); |
| 2393 | 247 debug_printf("loaded plugin returned %s\n", retval ? retval : "NULL"); |
| 248 if (retval) { | |
| 249 plugin_remove_callbacks(plug->handle); | |
| 3427 | 250 do_error_dialog("Gaim was unable to load your plugin.", retval, GAIM_ERROR); |
| 2393 | 251 g_module_close(plug->handle); |
| 3551 | 252 plug->handle = NULL; |
| 2393 | 253 return NULL; |
| 254 } | |
| 255 | |
| 256 plugins = g_list_append(plugins, plug); | |
| 257 | |
| 3551 | 258 if (newplug) { |
| 259 g_snprintf(plug->path, sizeof(plug->path), filename); | |
| 260 if (g_module_symbol(plug->handle, "gaim_plugin_desc", (gpointer *)&gaim_plugin_desc)) { | |
| 261 desc = gaim_plugin_desc(); | |
| 262 plug->desc.name = desc->name; | |
| 263 } else { | |
| 264 if (g_module_symbol(plug->handle, "name", (gpointer *)&cfunc)) { | |
| 265 plug->desc.name = g_strdup(cfunc()); | |
| 266 } | |
| 267 if (g_module_symbol(plug->handle, "description", (gpointer *)&cfunc)) { | |
| 268 plug->desc.description = g_strdup(cfunc()); | |
| 269 } | |
| 270 } | |
| 271 probed_plugins = g_list_append(probed_plugins, plug); | |
| 2393 | 272 } |
| 3551 | 273 |
| 2393 | 274 save_prefs(); |
| 275 return plug; | |
| 3551 | 276 |
| 2393 | 277 } |
| 278 | |
| 279 static void unload_gaim_plugin(struct gaim_plugin *p) | |
| 280 { | |
| 281 void (*gaim_plugin_remove)(); | |
| 282 | |
| 283 debug_printf("Unloading %s\n", g_module_name(p->handle)); | |
| 284 | |
| 285 /* Attempt to call the plugin's remove function (if there) */ | |
| 286 if (g_module_symbol(p->handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove)) | |
|
2662
b0c5770156e1
[gaim-migrate @ 2675]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2511
diff
changeset
|
287 gaim_plugin_remove(); |
| 2393 | 288 |
| 289 plugin_remove_callbacks(p->handle); | |
| 290 | |
| 291 plugins = g_list_remove(plugins, p); | |
| 3551 | 292 p->handle = NULL; |
| 2393 | 293 save_prefs(); |
| 294 } | |
| 295 | |
| 296 void unload_plugin(struct gaim_plugin *p) | |
| 297 { | |
| 298 GModule *handle = p->handle; | |
| 299 unload_gaim_plugin(p); | |
| 300 g_module_close(handle); | |
| 301 } | |
| 302 | |
| 303 static gboolean unload_timeout(gpointer handle) | |
| 304 { | |
| 305 g_module_close(handle); | |
| 306 return FALSE; | |
| 307 } | |
| 308 | |
| 309 void gaim_plugin_unload(GModule *handle) | |
| 310 { | |
|
2494
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
311 GList *pl = plugins; |
|
2511
a83b4a5ffcd6
[gaim-migrate @ 2524]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2494
diff
changeset
|
312 struct gaim_plugin *p = NULL; |
|
2494
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
313 void (*gaim_plugin_remove)(); |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
314 |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
315 while (pl) { |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
316 p = pl->data; |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
317 if (p->handle == handle) |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
318 break; |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
319 pl = pl->next; |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
320 } |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
321 if (!pl) |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
322 return; |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
323 |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
324 debug_printf("Unloading %s\n", g_module_name(p->handle)); |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
325 |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
326 if (g_module_symbol(p->handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove)) |
|
2662
b0c5770156e1
[gaim-migrate @ 2675]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2511
diff
changeset
|
327 gaim_plugin_remove(); |
|
2494
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
328 plugin_remove_callbacks(p->handle); |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
329 plugins = g_list_remove(plugins, p); |
|
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
330 g_free(p); |
| 3551 | 331 /* XXX CUI need to tell UI what happened, but not like this |
| 332 update_show_plugins(); */ | |
|
2494
2c1950c5544a
[gaim-migrate @ 2507]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2465
diff
changeset
|
333 |
| 2393 | 334 g_timeout_add(5000, unload_timeout, handle); |
| 335 } | |
| 336 | |
| 337 /* Do unload/load cycle of plugin. */ | |
| 338 struct gaim_plugin *reload_plugin(struct gaim_plugin *p) | |
| 339 { | |
| 340 char file[1024]; | |
| 341 GModule *handle = p->handle; | |
| 342 | |
| 343 strncpy(file, g_module_name(handle), sizeof(file)); | |
| 344 file[sizeof(file) - 1] = '\0'; | |
| 345 | |
| 346 debug_printf("Reloading %s\n", file); | |
| 347 | |
| 348 /* Unload */ | |
| 349 unload_plugin(p); | |
| 350 | |
| 351 /* Load */ | |
| 352 return load_plugin(file); | |
| 353 } | |
| 354 | |
| 355 /* Remove all callbacks associated with plugin handle */ | |
| 356 static void plugin_remove_callbacks(GModule *handle) | |
| 357 { | |
| 358 GList *c = callbacks; | |
| 359 struct gaim_callback *g; | |
| 360 | |
| 361 debug_printf("%d callbacks to search\n", g_list_length(callbacks)); | |
| 362 | |
| 363 while (c) { | |
| 364 g = (struct gaim_callback *)c->data; | |
| 365 if (g->handle == handle) { | |
| 366 c = g_list_next(c); | |
| 367 callbacks = g_list_remove(callbacks, (gpointer)g); | |
| 368 debug_printf("Removing callback, %d remain\n", g_list_length(callbacks)); | |
| 369 } else | |
| 370 c = g_list_next(c); | |
| 371 } | |
| 372 } | |
| 373 | |
| 374 void gaim_signal_connect(GModule *handle, enum gaim_event which, void *func, void *data) | |
| 375 { | |
| 376 struct gaim_callback *call = g_new0(struct gaim_callback, 1); | |
| 377 call->handle = handle; | |
| 378 call->event = which; | |
| 379 call->function = func; | |
| 380 call->data = data; | |
| 381 | |
| 382 callbacks = g_list_append(callbacks, call); | |
| 383 debug_printf("Adding callback %d\n", g_list_length(callbacks)); | |
| 384 } | |
| 385 | |
| 386 void gaim_signal_disconnect(GModule *handle, enum gaim_event which, void *func) | |
| 387 { | |
| 388 GList *c = callbacks; | |
| 389 struct gaim_callback *g = NULL; | |
| 390 | |
| 391 while (c) { | |
| 392 g = (struct gaim_callback *)c->data; | |
| 393 if (handle == g->handle && func == g->function) { | |
| 394 callbacks = g_list_remove(callbacks, c->data); | |
| 395 g_free(g); | |
| 396 c = callbacks; | |
| 397 if (c == NULL) | |
| 398 break; | |
| 399 } | |
| 400 c = g_list_next(c); | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 #endif /* GAIM_PLUGINS */ | |
| 405 | |
|
2511
a83b4a5ffcd6
[gaim-migrate @ 2524]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2494
diff
changeset
|
406 char *event_name(enum gaim_event event) |
| 2393 | 407 { |
| 408 static char buf[128]; | |
| 409 switch (event) { | |
| 410 case event_signon: | |
| 411 sprintf(buf, "event_signon"); | |
| 412 break; | |
| 413 case event_signoff: | |
| 414 sprintf(buf, "event_signoff"); | |
| 415 break; | |
| 416 case event_away: | |
| 417 sprintf(buf, "event_away"); | |
| 418 break; | |
| 419 case event_back: | |
| 420 sprintf(buf, "event_back"); | |
| 421 break; | |
| 422 case event_im_recv: | |
| 423 sprintf(buf, "event_im_recv"); | |
| 424 break; | |
| 425 case event_im_send: | |
| 426 sprintf(buf, "event_im_send"); | |
| 427 break; | |
| 428 case event_buddy_signon: | |
| 429 sprintf(buf, "event_buddy_signon"); | |
| 430 break; | |
| 431 case event_buddy_signoff: | |
| 432 sprintf(buf, "event_buddy_signoff"); | |
| 433 break; | |
| 434 case event_buddy_away: | |
| 435 sprintf(buf, "event_buddy_away"); | |
| 436 break; | |
| 437 case event_buddy_back: | |
| 438 sprintf(buf, "event_buddy_back"); | |
| 439 break; | |
| 440 case event_buddy_idle: | |
| 441 sprintf(buf, "event_buddy_idle"); | |
| 442 break; | |
| 443 case event_buddy_unidle: | |
| 444 sprintf(buf, "event_buddy_unidle"); | |
| 445 break; | |
| 446 case event_blist_update: | |
| 447 sprintf(buf, "event_blist_update"); | |
| 448 break; | |
| 449 case event_chat_invited: | |
| 450 sprintf(buf, "event_chat_invited"); | |
| 451 break; | |
| 452 case event_chat_join: | |
| 453 sprintf(buf, "event_chat_join"); | |
| 454 break; | |
| 455 case event_chat_leave: | |
| 456 sprintf(buf, "event_chat_leave"); | |
| 457 break; | |
| 458 case event_chat_buddy_join: | |
| 459 sprintf(buf, "event_chat_buddy_join"); | |
| 460 break; | |
| 461 case event_chat_buddy_leave: | |
| 462 sprintf(buf, "event_chat_buddy_leave"); | |
| 463 break; | |
| 464 case event_chat_recv: | |
| 465 sprintf(buf, "event_chat_recv"); | |
| 466 break; | |
| 467 case event_chat_send: | |
| 468 sprintf(buf, "event_chat_send"); | |
| 469 break; | |
| 470 case event_warned: | |
| 471 sprintf(buf, "event_warned"); | |
| 472 break; | |
| 473 case event_error: | |
| 474 sprintf(buf, "event_error"); | |
| 475 break; | |
| 476 case event_quit: | |
| 477 sprintf(buf, "event_quit"); | |
| 478 break; | |
| 479 case event_new_conversation: | |
| 480 sprintf(buf, "event_new_conversation"); | |
| 481 break; | |
| 482 case event_set_info: | |
| 483 sprintf(buf, "event_set_info"); | |
| 484 break; | |
| 485 case event_draw_menu: | |
| 486 sprintf(buf, "event_draw_menu"); | |
| 487 break; | |
| 488 case event_im_displayed_sent: | |
| 489 sprintf(buf, "event_im_displayed_sent"); | |
| 490 break; | |
| 491 case event_im_displayed_rcvd: | |
| 492 sprintf(buf, "event_im_displayed_rcvd"); | |
| 493 break; | |
| 494 case event_chat_send_invite: | |
| 495 sprintf(buf, "event_chat_send_invite"); | |
| 496 break; | |
| 2993 | 497 case event_got_typing: |
| 498 sprintf(buf, "event_got_typing"); | |
| 499 break; | |
| 3510 | 500 case event_del_conversation: |
| 501 sprintf(buf, "event_del_conversation"); | |
| 502 break; | |
| 503 case event_connecting: | |
| 504 sprintf(buf, "event_connecting"); | |
| 505 break; | |
| 2393 | 506 default: |
| 507 sprintf(buf, "event_unknown"); | |
| 508 break; | |
| 509 } | |
| 510 return buf; | |
| 511 } | |
| 512 | |
| 3517 | 513 int plugin_event(enum gaim_event event, ...) |
| 2393 | 514 { |
| 515 #ifdef GAIM_PLUGINS | |
| 516 GList *c = callbacks; | |
| 517 struct gaim_callback *g; | |
| 3551 | 518 #endif |
| 3517 | 519 va_list arrg; |
| 520 void *arg1 = NULL, | |
| 521 *arg2 = NULL, | |
| 522 *arg3 = NULL, | |
| 523 *arg4 = NULL, | |
| 524 *arg5 = NULL; | |
| 3551 | 525 |
| 2393 | 526 |
| 3517 | 527 debug_printf("%s\n", event_name(event)); |
|
2463
0be6fadaa64f
[gaim-migrate @ 2476]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2443
diff
changeset
|
528 |
|
0be6fadaa64f
[gaim-migrate @ 2476]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2443
diff
changeset
|
529 #ifdef GAIM_PLUGINS |
| 2393 | 530 while (c) { |
| 3517 | 531 void (*cbfunc)(void *, ...); |
| 532 | |
| 2393 | 533 g = (struct gaim_callback *)c->data; |
|
2511
a83b4a5ffcd6
[gaim-migrate @ 2524]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2494
diff
changeset
|
534 if (g->event == event && g->function != NULL) { |
| 3517 | 535 cbfunc=g->function; |
| 536 va_start(arrg, event); | |
| 2393 | 537 switch (event) { |
| 538 | |
| 539 /* no args */ | |
| 540 case event_blist_update: | |
| 541 case event_quit: | |
| 3517 | 542 cbfunc(g->data); |
| 2393 | 543 break; |
| 544 | |
| 545 /* one arg */ | |
| 546 case event_signon: | |
| 547 case event_signoff: | |
| 548 case event_new_conversation: | |
| 3461 | 549 case event_del_conversation: |
| 2393 | 550 case event_error: |
| 3510 | 551 case event_connecting: |
| 3517 | 552 arg1 = va_arg(arrg, void *); |
| 553 cbfunc(arg1, g->data); | |
| 2393 | 554 break; |
| 555 | |
| 556 /* two args */ | |
| 557 case event_buddy_signon: | |
| 558 case event_buddy_signoff: | |
| 559 case event_buddy_away: | |
| 560 case event_buddy_back: | |
| 561 case event_buddy_idle: | |
| 562 case event_buddy_unidle: | |
| 563 case event_set_info: | |
| 564 case event_draw_menu: | |
| 2993 | 565 case event_got_typing: |
| 3517 | 566 arg1 = va_arg(arrg, void *); |
| 567 arg2 = va_arg(arrg, void *); | |
| 568 cbfunc(arg1, arg2, g->data); | |
| 2393 | 569 break; |
| 3517 | 570 case event_chat_leave: |
| 571 { | |
| 572 int id; | |
| 573 arg1 = va_arg(arrg, void*); | |
| 574 id = va_arg(arrg, int); | |
| 575 cbfunc(arg1, id, g->data); | |
| 576 } | |
| 577 break; | |
| 2393 | 578 /* three args */ |
| 579 case event_im_send: | |
| 580 case event_im_displayed_sent: | |
| 3517 | 581 case event_away: |
| 582 arg1 = va_arg(arrg, void *); | |
| 583 arg2 = va_arg(arrg, void *); | |
| 584 arg3 = va_arg(arrg, void *); | |
| 585 cbfunc(arg1, arg2, arg3, g->data); | |
| 586 break; | |
| 2393 | 587 case event_chat_buddy_join: |
| 588 case event_chat_buddy_leave: | |
| 589 case event_chat_send: | |
| 3517 | 590 case event_chat_join: |
| 591 { | |
| 592 int id; | |
| 593 arg1 = va_arg(arrg, void*); | |
| 594 id = va_arg(arrg, int); | |
| 595 arg3 = va_arg(arrg, void*); | |
| 596 cbfunc(arg1, id, arg3, g->data); | |
| 597 } | |
| 598 break; | |
| 2393 | 599 case event_warned: |
| 3517 | 600 { |
| 601 int id; | |
| 602 arg1 = va_arg(arrg, void*); | |
| 603 arg2 = va_arg(arrg, void*); | |
| 604 id = va_arg(arrg, int); | |
| 605 cbfunc(arg1, arg2, id, g->data); | |
| 606 } | |
| 2393 | 607 break; |
| 608 /* four args */ | |
| 609 case event_im_recv: | |
| 3517 | 610 case event_chat_invited: |
| 611 arg1 = va_arg(arrg, void *); | |
| 612 arg2 = va_arg(arrg, void *); | |
| 613 arg3 = va_arg(arrg, void *); | |
| 614 arg4 = va_arg(arrg, void *); | |
| 615 cbfunc(arg1, arg2, arg3, arg4, g->data); | |
| 616 break; | |
| 2393 | 617 case event_chat_recv: |
| 618 case event_chat_send_invite: | |
| 3517 | 619 { |
| 620 int id; | |
| 621 arg1 = va_arg(arrg, void *); | |
| 622 id = va_arg(arrg, int); | |
| 623 | |
| 624 arg3 = va_arg(arrg, void *); | |
| 625 arg4 = va_arg(arrg, void *); | |
| 626 cbfunc(arg1, id, arg3, arg4, g->data); | |
| 627 } | |
| 2393 | 628 break; |
| 3517 | 629 /* five args */ |
| 630 case event_im_displayed_rcvd: | |
| 631 { | |
| 632 time_t time; | |
| 633 arg1 = va_arg(arrg, void *); | |
| 634 arg2 = va_arg(arrg, void *); | |
| 635 arg3 = va_arg(arrg, void *); | |
| 636 arg4 = va_arg(arrg, void *); | |
| 637 time = va_arg(arrg, time_t); | |
| 638 cbfunc(arg1, arg2, arg3, arg4, time, g->data); | |
| 639 } | |
| 640 break; | |
| 641 default: | |
| 2393 | 642 debug_printf("unknown event %d\n", event); |
| 643 break; | |
| 644 } | |
| 3517 | 645 va_end(arrg); |
| 2393 | 646 } |
| 647 c = c->next; | |
| 648 } | |
| 649 #endif /* GAIM_PLUGINS */ | |
| 650 #ifdef USE_PERL | |
| 3517 | 651 va_start(arrg, event); |
| 652 arg1 = va_arg(arrg, void *); | |
| 653 arg2 = va_arg(arrg, void *); | |
| 654 arg3 = va_arg(arrg, void *); | |
| 655 arg4 = va_arg(arrg, void *); | |
| 656 arg5 = va_arg(arrg, void *); | |
| 657 return perl_event(event, arg1, arg2, arg3, arg4, arg5); | |
| 2393 | 658 #else |
| 659 return 0; | |
| 660 #endif | |
| 661 } | |
| 662 | |
| 663 /* Calls the gaim_plugin_remove function in any loaded plugin that has one */ | |
| 664 #ifdef GAIM_PLUGINS | |
| 665 void remove_all_plugins() | |
| 666 { | |
| 667 GList *c = plugins; | |
| 668 struct gaim_plugin *p; | |
| 669 void (*gaim_plugin_remove)(); | |
| 670 | |
| 671 while (c) { | |
| 672 p = (struct gaim_plugin *)c->data; | |
| 3563 | 673 if (p->type == plugin) { |
| 674 if (g_module_symbol(p->handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove)) | |
| 675 gaim_plugin_remove(); | |
| 676 } | |
| 2393 | 677 g_free(p); |
| 678 c = c->next; | |
| 679 } | |
| 680 } | |
| 681 #endif |
