Mercurial > pidgin.yaz
annotate plugins/perl/perl.c @ 5665:132a30783c3d
[gaim-migrate @ 6081]
We're going to shuffle around the init sequence in main.c again. Importing
accounts should no longer screw things up, and there's better protection
against invalid protocol IDs causing an account to have to be hand-editted.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Mon, 02 Jun 2003 10:21:33 +0000 |
parents | cde28f5c47d4 |
children | dae79aefac8d |
rev | line source |
---|---|
5205 | 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 * This was taken almost exactly from X-Chat. The power of the GPL. | |
21 * Translated from X-Chat to Gaim by Eric Warmenhoven. | |
22 * Originally by Erik Scrafford <eriks@chilisoft.com>. | |
23 * X-Chat Copyright (C) 1998 Peter Zelezny. | |
24 * | |
25 */ | |
26 | |
27 #ifdef HAVE_CONFIG_H | |
28 #include <config.h> | |
29 #ifdef DEBUG | |
30 #undef DEBUG | |
31 #endif | |
32 #endif | |
33 #undef PACKAGE | |
34 | |
35 #define group perl_group | |
36 #ifdef _WIN32 | |
37 /* This took me an age to figure out.. without this __declspec(dllimport) | |
38 * will be ignored. | |
39 */ | |
40 #define HASATTRIBUTE | |
41 #endif | |
42 #include <EXTERN.h> | |
43 #ifndef _SEM_SEMUN_UNDEFINED | |
44 #define HAS_UNION_SEMUN | |
45 #endif | |
46 #include <perl.h> | |
47 #include <XSUB.h> | |
48 #ifndef _WIN32 | |
49 #include <sys/mman.h> | |
50 #endif | |
51 #include <sys/types.h> | |
52 #include <sys/stat.h> | |
53 #include <fcntl.h> | |
54 #undef PACKAGE | |
55 #include <stdio.h> | |
56 #ifndef _WIN32 | |
57 #include <dirent.h> | |
58 #else | |
59 /* We're using perl's win32 port of this */ | |
60 #define dirent direct | |
61 #endif | |
62 #include <string.h> | |
63 | |
64 #undef group | |
65 | |
66 /* perl module support */ | |
67 #ifdef OLD_PERL | |
68 extern void boot_DynaLoader _((CV * cv)); | |
69 #else | |
70 extern void boot_DynaLoader _((pTHX_ CV * cv)); /* perl is so wacky */ | |
71 #endif | |
72 | |
73 #undef _ | |
74 #ifdef DEBUG | |
75 #undef DEBUG | |
76 #endif | |
77 #ifdef _WIN32 | |
78 #undef pipe | |
79 #endif | |
80 #include "gaim.h" | |
81 #include "prpl.h" | |
82 #include "sound.h" | |
83 | |
84 #ifndef call_pv | |
85 # define call_pv(i,j) perl_call_pv((i), (j)) | |
86 #endif | |
87 | |
88 #define PERL_PLUGIN_ID "core-perl" | |
89 | |
90 struct perlscript { | |
91 char *name; | |
92 char *version; | |
93 char *shutdowncallback; /* bleh */ | |
94 GaimPlugin *plug; | |
95 }; | |
96 | |
97 struct _perl_event_handlers { | |
98 char *event_type; | |
99 char *handler_name; | |
100 GaimPlugin *plug; | |
101 }; | |
102 | |
103 struct _perl_timeout_handlers { | |
104 char *handler_name; | |
105 char *handler_args; | |
106 gint iotag; | |
107 GaimPlugin *plug; | |
108 }; | |
109 | |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5408
diff
changeset
|
110 static GaimPlugin *my_plugin = NULL; |
5205 | 111 static GList *perl_list = NULL; |
112 static GList *perl_timeout_handlers = NULL; | |
113 static GList *perl_event_handlers = NULL; | |
114 static PerlInterpreter *my_perl = NULL; | |
115 static void perl_init(); | |
116 | |
117 /* dealing with gaim */ | |
118 XS(XS_GAIM_register); /* set up hooks for script */ | |
119 XS(XS_GAIM_get_info); /* version, last to attempt signon, protocol */ | |
120 XS(XS_GAIM_print); /* lemme figure this one out... */ | |
121 XS(XS_GAIM_write_to_conv); /* write into conversation window */ | |
122 | |
123 /* list stuff */ | |
124 XS(XS_GAIM_buddy_list); /* all buddies */ | |
125 XS(XS_GAIM_online_list); /* online buddies */ | |
126 | |
127 /* server stuff */ | |
128 XS(XS_GAIM_command); /* send command to server */ | |
129 XS(XS_GAIM_user_info); /* given name, return struct buddy members */ | |
130 XS(XS_GAIM_print_to_conv); /* send message to someone */ | |
131 XS(XS_GAIM_print_to_chat); /* send message to chat room */ | |
132 XS(XS_GAIM_serv_send_im); /* send message to someone (but do not display) */ | |
133 | |
134 /* handler commands */ | |
135 XS(XS_GAIM_add_event_handler); /* when servers talk */ | |
136 XS(XS_GAIM_remove_event_handler); /* remove a handler */ | |
137 XS(XS_GAIM_add_timeout_handler); /* figure it out */ | |
138 | |
139 /* play sound */ | |
140 XS(XS_GAIM_play_sound); /*play a sound */ | |
141 | |
142 static void | |
143 #ifdef OLD_PERL | |
144 xs_init() | |
145 #else | |
146 xs_init(pTHX) | |
147 #endif | |
148 { | |
149 char *file = __FILE__; | |
150 | |
151 /* This one allows dynamic loading of perl modules in perl | |
152 scripts by the 'use perlmod;' construction*/ | |
153 newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); | |
154 | |
155 /* load up all the custom Gaim perl functions */ | |
156 newXS ("GAIM::register", XS_GAIM_register, "GAIM"); | |
157 newXS ("GAIM::get_info", XS_GAIM_get_info, "GAIM"); | |
158 newXS ("GAIM::print", XS_GAIM_print, "GAIM"); | |
159 newXS ("GAIM::write_to_conv", XS_GAIM_write_to_conv, "GAIM"); | |
160 | |
161 newXS ("GAIM::buddy_list", XS_GAIM_buddy_list, "GAIM"); | |
162 newXS ("GAIM::online_list", XS_GAIM_online_list, "GAIM"); | |
163 | |
164 newXS ("GAIM::command", XS_GAIM_command, "GAIM"); | |
165 newXS ("GAIM::user_info", XS_GAIM_user_info, "GAIM"); | |
166 newXS ("GAIM::print_to_conv", XS_GAIM_print_to_conv, "GAIM"); | |
167 newXS ("GAIM::print_to_chat", XS_GAIM_print_to_chat, "GAIM"); | |
168 newXS ("GAIM::serv_send_im", XS_GAIM_serv_send_im, "GAIM"); | |
169 | |
170 newXS ("GAIM::add_event_handler", XS_GAIM_add_event_handler, "GAIM"); | |
171 newXS ("GAIM::remove_event_handler", XS_GAIM_remove_event_handler, "GAIM"); | |
172 newXS ("GAIM::add_timeout_handler", XS_GAIM_add_timeout_handler, "GAIM"); | |
173 | |
174 newXS ("GAIM::play_sound", XS_GAIM_play_sound, "GAIM"); | |
175 } | |
176 | |
177 static char * | |
178 escape_quotes(const char *buf) | |
179 { | |
180 static char *tmp_buf = NULL; | |
181 const char *i; | |
182 char *j; | |
183 | |
184 if (tmp_buf) | |
185 g_free(tmp_buf); | |
186 | |
187 tmp_buf = g_malloc(strlen(buf) * 2 + 1); | |
188 | |
189 for (i = buf, j = tmp_buf; *i; i++, j++) { | |
190 if (*i == '\'' || *i == '\\') | |
191 *j++ = '\\'; | |
192 | |
193 *j = *i; | |
194 } | |
195 | |
196 *j = '\0'; | |
197 | |
198 return tmp_buf; | |
199 } | |
200 | |
201 /* | |
202 2003/02/06: execute_perl modified by Mark Doliner <mark@kingant.net> | |
203 Pass parameters by pushing them onto the stack rather than | |
204 passing an array of strings. This way, perl scripts can | |
205 modify the parameters and we can get the changed values | |
206 and then shoot ourselves. I mean, uh, use them. | |
207 | |
208 2001/06/14: execute_perl replaced by Martin Persson <mep@passagen.se> | |
209 previous use of perl_eval leaked memory, replaced with | |
210 a version that uses perl_call instead | |
211 | |
212 30/11/2002: execute_perl modified by Eric Timme <timothy@voidnet.com> | |
213 args changed to char** so that we can have preparsed | |
214 arguments again, and many headaches ensued! This essentially | |
215 means we replaced one hacked method with a messier hacked | |
216 method out of perceived necessity. Formerly execute_perl | |
217 required a single char_ptr, and it would insert it into an | |
218 array of character pointers and NULL terminate the new array. | |
219 Now we have to pass in pre-terminated character pointer arrays | |
220 to accomodate functions that want to pass in multiple arguments. | |
221 | |
222 Previously arguments were preparsed because an argument list | |
223 was constructed in the form 'arg one','arg two' and was | |
224 executed via a call like &funcname(arglist) (see .59.x), so | |
225 the arglist was magically pre-parsed because of the method. | |
226 With Martin Persson's change to perl_call we now need to | |
227 use a null terminated list of character pointers for arguments | |
228 if we wish them to be parsed. Lacking a better way to allow | |
229 for both single arguments and many I created a NULL terminated | |
230 array in every function that called execute_perl and passed | |
231 that list into the function. In the former version a single | |
232 character pointer was passed in, and was placed into an array | |
233 of character pointers with two elements, with a NULL element | |
234 tacked onto the back, but this method no longer seemed prudent. | |
235 | |
236 Enhancements in the future might be to get rid of pre-declaring | |
237 the array sizes? I am not comfortable enough with this | |
238 subject to attempt it myself and hope it to stand the test | |
239 of time. | |
240 */ | |
241 | |
242 static int | |
243 execute_perl(const char *function, int argc, char **args) | |
244 { | |
245 int count = 0, i, ret_value = 1; | |
246 SV *sv_args[argc]; | |
247 STRLEN na; | |
248 | |
249 /* | |
250 * Set up the perl environment, push arguments onto the | |
251 * perl stack, then call the given function | |
252 */ | |
253 dSP; | |
254 ENTER; | |
255 SAVETMPS; | |
256 PUSHMARK(sp); | |
257 | |
258 for (i = 0; i < argc; i++) { | |
259 if (args[i]) { | |
260 sv_args[i] = sv_2mortal(newSVpv(args[i], 0)); | |
261 XPUSHs(sv_args[i]); | |
262 } | |
263 } | |
264 | |
265 PUTBACK; | |
266 count = call_pv(function, G_EVAL | G_SCALAR); | |
267 SPAGAIN; | |
268 | |
269 /* | |
270 * Check for "die," make sure we have 1 argument, and set our | |
271 * return value. | |
272 */ | |
273 if (SvTRUE(ERRSV)) { | |
5227
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
274 gaim_debug(GAIM_DEBUG_ERROR, "perl", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
275 "Perl function %s exited abnormally: %s\n", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
276 function, SvPV(ERRSV, na)); |
5205 | 277 POPs; |
278 } | |
279 else if (count != 1) { | |
280 /* | |
281 * This should NEVER happen. G_SCALAR ensures that we WILL | |
282 * have 1 parameter. | |
283 */ | |
5227
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
284 gaim_debug(GAIM_DEBUG_ERROR, "perl", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
285 "Perl error from %s: expected 1 return value, " |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
286 "but got %d\n", function, count); |
5205 | 287 } |
288 else | |
289 ret_value = POPi; | |
290 | |
291 /* Check for changed arguments */ | |
292 for (i = 0; i < argc; i++) { | |
293 if (args[i] && strcmp(args[i], SvPVX(sv_args[i]))) { | |
294 /* | |
295 * Shizzel. So the perl script changed one of the parameters, | |
296 * and we want this change to affect the original parameters. | |
297 * args[i] is just a tempory little list of pointers. We don't | |
298 * want to free args[i] here because the new parameter doesn't | |
299 * overwrite the data that args[i] points to. That is done by | |
300 * the function that called execute_perl. I'm not explaining this | |
301 * very well. See, it's aggregate... Oh, but if 2 perl scripts | |
302 * both modify the data, _that's_ a memleak. This is really kind | |
303 * of hackish. I should fix it. Look how long this comment is. | |
304 * Holy crap. | |
305 */ | |
306 args[i] = g_strdup(SvPV(sv_args[i], na)); | |
307 } | |
308 } | |
309 | |
310 PUTBACK; | |
311 FREETMPS; | |
312 LEAVE; | |
313 | |
314 return ret_value; | |
315 } | |
316 | |
317 static void | |
318 perl_unload_file(GaimPlugin *plug) | |
319 { | |
320 char *atmp[2] = { "", NULL }; | |
321 struct perlscript *scp = NULL; | |
322 struct _perl_timeout_handlers *thn; | |
323 struct _perl_event_handlers *ehn; | |
324 GList *pl; | |
325 | |
326 for (pl = perl_list; pl != NULL; pl = pl->next) { | |
327 scp = pl->data; | |
328 | |
329 if (scp->plug == plug) { | |
330 perl_list = g_list_remove(perl_list, scp); | |
331 | |
332 if (scp->shutdowncallback[0]) | |
333 execute_perl(scp->shutdowncallback, 1, atmp); | |
334 | |
335 g_free(scp->name); | |
336 g_free(scp->version); | |
337 g_free(scp->shutdowncallback); | |
338 g_free(scp); | |
339 | |
340 break; | |
341 } | |
342 } | |
343 | |
344 for (pl = perl_timeout_handlers; pl != NULL; pl = pl->next) { | |
345 thn = pl->data; | |
346 | |
347 if (thn && thn->plug == plug) { | |
348 perl_timeout_handlers = g_list_remove(perl_timeout_handlers, thn); | |
349 | |
350 g_source_remove(thn->iotag); | |
351 g_free(thn->handler_args); | |
352 g_free(thn->handler_name); | |
353 g_free(thn); | |
354 } | |
355 } | |
356 | |
357 for (pl = perl_event_handlers; pl != NULL; pl = pl->next) { | |
358 ehn = pl->data; | |
359 | |
360 if (ehn && ehn->plug == plug) { | |
361 perl_event_handlers = g_list_remove(perl_event_handlers, ehn); | |
362 | |
363 g_free(ehn->event_type); | |
364 g_free(ehn->handler_name); | |
365 g_free(ehn); | |
366 } | |
367 } | |
368 } | |
369 | |
370 static int | |
371 perl_load_file(char *script_name, GaimPlugin *plugin) | |
372 { | |
373 char *atmp[2] = { script_name, NULL }; | |
374 GList *s; | |
375 struct perlscript *scp; | |
376 int ret; | |
377 | |
378 if (my_perl == NULL) | |
379 perl_init(); | |
380 | |
381 plugin->handle = plugin->path; | |
382 | |
383 ret = execute_perl("load_n_eval", 1, atmp); | |
384 | |
385 for (s = perl_list; s != NULL; s = s->next) { | |
386 scp = s->data; | |
387 | |
388 if (!strcmp(scp->name, plugin->info->name) && | |
389 !strcmp(scp->version, plugin->info->version)) { | |
390 | |
391 break; | |
392 } | |
393 } | |
394 | |
395 if (!s) { | |
396 plugin->error = g_strdup(_("GAIM::register not called with " | |
397 "proper arguments. Consult PERL-HOWTO.")); | |
398 | |
399 return 0; | |
400 } | |
401 | |
402 return ret; | |
403 } | |
404 | |
405 static void | |
406 perl_init(void) | |
407 { | |
408 /* changed the name of the variable from load_file to | |
409 perl_definitions since now it does much more than defining | |
410 the load_file sub. Moreover, deplaced the initialisation to | |
411 the xs_init function. (TheHobbit)*/ | |
412 char *perl_args[] = { "", "-e", "0", "-w" }; | |
413 char perl_definitions[] = | |
414 { | |
415 /* We use to function one to load a file the other to | |
416 execute the string obtained from the first and holding | |
417 the file conents. This allows to have a realy local $/ | |
418 without introducing temp variables to hold the old | |
419 value. Just a question of style:) */ | |
420 "sub load_file{" | |
421 "my $f_name=shift;" | |
422 "local $/=undef;" | |
423 "open FH,$f_name or return \"__FAILED__\";" | |
424 "$_=<FH>;" | |
425 "close FH;" | |
426 "return $_;" | |
427 "}" | |
428 "sub load_n_eval{" | |
429 "my $f_name=shift;" | |
430 "my $strin=load_file($f_name);" | |
431 "return 2 if($strin eq \"__FAILED__\");" | |
432 "eval $strin;" | |
433 "if($@){" | |
434 /*" #something went wrong\n"*/ | |
435 "GAIM::print(\"Errors loading file $f_name:\\n\",\"$@\");" | |
436 "return 1;" | |
437 "}" | |
438 "return 0;" | |
439 "}" | |
440 }; | |
441 | |
442 my_perl = perl_alloc(); | |
443 perl_construct(my_perl); | |
444 #ifdef DEBUG | |
445 perl_parse(my_perl, xs_init, 4, perl_args, NULL); | |
446 #else | |
447 perl_parse(my_perl, xs_init, 3, perl_args, NULL); | |
448 #endif | |
449 #ifdef HAVE_PERL_EVAL_PV | |
450 eval_pv(perl_definitions, TRUE); | |
451 #else | |
452 perl_eval_pv(perl_definitions, TRUE); /* deprecated */ | |
453 #endif | |
454 } | |
455 | |
456 static void | |
457 perl_end(void) | |
458 { | |
459 char *atmp[2] = { "", NULL }; | |
460 struct perlscript *scp; | |
461 struct _perl_timeout_handlers *thn; | |
462 struct _perl_event_handlers *ehn; | |
463 | |
464 while (perl_list) { | |
465 scp = perl_list->data; | |
466 perl_list = g_list_remove(perl_list, scp); | |
467 | |
468 if (scp->shutdowncallback[0]) | |
469 execute_perl(scp->shutdowncallback, 1, atmp); | |
470 | |
471 g_free(scp->name); | |
472 g_free(scp->version); | |
473 g_free(scp->shutdowncallback); | |
474 g_free(scp); | |
475 } | |
476 | |
477 while (perl_timeout_handlers) { | |
478 thn = perl_timeout_handlers->data; | |
479 perl_timeout_handlers = g_list_remove(perl_timeout_handlers, thn); | |
480 g_source_remove(thn->iotag); | |
481 g_free(thn->handler_args); | |
482 g_free(thn->handler_name); | |
483 g_free(thn); | |
484 } | |
485 | |
486 while (perl_event_handlers) { | |
487 ehn = perl_event_handlers->data; | |
488 perl_event_handlers = g_list_remove(perl_event_handlers, ehn); | |
489 g_free(ehn->event_type); | |
490 g_free(ehn->handler_name); | |
491 g_free(ehn); | |
492 } | |
493 | |
494 if (my_perl != NULL) { | |
495 perl_destruct(my_perl); | |
496 perl_free(my_perl); | |
497 my_perl = NULL; | |
498 } | |
499 } | |
500 | |
501 XS (XS_GAIM_register) | |
502 { | |
503 char *name, *ver, *callback, *unused; /* exactly like X-Chat, eh? :) */ | |
504 unsigned int junk; | |
505 struct perlscript *scp; | |
506 GaimPlugin *plug = NULL; | |
507 GList *pl; | |
508 | |
509 dXSARGS; | |
510 items = 0; | |
511 | |
512 name = SvPV(ST(0), junk); | |
513 ver = SvPV(ST(1), junk); | |
514 callback = SvPV(ST(2), junk); | |
515 unused = SvPV(ST(3), junk); | |
516 | |
5227
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
517 gaim_debug(GAIM_DEBUG_INFO, "perl", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
518 "GAIM::register(%s, %s)\n", name, ver); |
5205 | 519 |
520 for (pl = gaim_plugins_get_all(); pl != NULL; pl = pl->next) { | |
521 plug = pl->data; | |
522 | |
523 if (!strcmp(name, plug->info->name) && | |
524 !strcmp(ver, plug->info->version)) { | |
525 | |
526 break; | |
527 } | |
528 | |
529 plug = NULL; | |
530 } | |
531 | |
532 if (plug) { | |
533 scp = g_new0(struct perlscript, 1); | |
534 scp->name = g_strdup(name); | |
535 scp->version = g_strdup(ver); | |
536 scp->shutdowncallback = g_strdup(callback); | |
537 scp->plug = plug; | |
538 perl_list = g_list_append(perl_list, scp); | |
539 XST_mPV(0, plug->path); | |
540 } | |
541 else | |
542 XST_mPV(0, NULL); | |
543 | |
544 XSRETURN (1); | |
545 } | |
546 | |
547 XS (XS_GAIM_get_info) | |
548 { | |
549 int i = 0; | |
550 dXSARGS; | |
551 items = 0; | |
552 | |
553 switch(SvIV(ST(0))) { | |
554 case 0: | |
555 XST_mPV(0, VERSION); | |
556 i = 1; | |
557 break; | |
558 | |
559 case 1: | |
560 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
561 GList *c = gaim_connections_get_all(); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
562 GaimConnection *gc; |
5205 | 563 |
564 while (c) { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
565 gc = (GaimConnection *)c->data; |
5205 | 566 XST_mIV(i++, (guint)gc); |
567 c = c->next; | |
568 } | |
569 } | |
570 break; | |
571 | |
572 case 2: | |
573 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
574 GaimConnection *gc = |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
575 (GaimConnection *)SvIV(ST(1)); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
576 GaimAccount *account = gaim_connection_get_account(gc); |
5205 | 577 |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
578 if (g_list_find(gaim_connections_get_all(), gc)) |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
579 XST_mIV(i++, gaim_account_get_protocol(account)); |
5205 | 580 else |
581 XST_mIV(i++, -1); | |
582 } | |
583 break; | |
584 | |
585 case 3: | |
586 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
587 GaimConnection *gc = |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
588 (GaimConnection *)SvIV(ST(1)); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
589 GaimAccount *account = gaim_connection_get_account(gc); |
5205 | 590 |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
591 if (g_list_find(gaim_connections_get_all(), gc)) |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
592 XST_mPV(i++, gaim_account_get_username(account)); |
5205 | 593 else |
594 XST_mPV(i++, ""); | |
595 } | |
596 break; | |
597 | |
598 case 4: | |
599 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
600 GaimConnection *gc = |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
601 (GaimConnection *)SvIV(ST(1)); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
602 GaimAccount *account = gaim_connection_get_account(gc); |
5205 | 603 |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
604 if (g_list_find(gaim_connections_get_all(), gc)) |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
605 XST_mIV(i++, g_list_index(gaim_accounts_get_all(), |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
606 account)); |
5205 | 607 else |
608 XST_mIV(i++, -1); | |
609 } | |
610 break; | |
611 | |
612 case 5: | |
613 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
614 GList *a = gaim_accounts_get_all(); |
5205 | 615 while (a) { |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
616 GaimAccount *account = a->data; |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
617 XST_mPV(i++, gaim_account_get_username(account)); |
5205 | 618 a = a->next; |
619 } | |
620 } | |
621 break; | |
622 | |
623 case 6: | |
624 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
625 GList *a = gaim_accounts_get_all(); |
5205 | 626 while (a) { |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
627 GaimAccount *account = a->data; |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
628 XST_mIV(i++, gaim_account_get_protocol(account)); |
5205 | 629 a = a->next; |
630 } | |
631 } | |
632 break; | |
633 | |
634 case 7: | |
635 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
636 GaimConnection *gc = |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
637 (GaimConnection *)SvIV(ST(1)); |
5205 | 638 |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
639 if (g_list_find(gaim_connections_get_all(), gc)) |
5205 | 640 XST_mPV(i++, gc->prpl->info->name); |
641 else | |
642 XST_mPV(i++, "Unknown"); | |
643 } | |
644 break; | |
645 | |
646 default: | |
647 XST_mPV(0, "Error2"); | |
648 i = 1; | |
649 } | |
650 | |
651 XSRETURN(i); | |
652 } | |
653 | |
654 XS (XS_GAIM_print) | |
655 { | |
656 char *title; | |
657 char *message; | |
658 unsigned int junk; | |
659 dXSARGS; | |
660 items = 0; | |
661 | |
662 title = SvPV(ST(0), junk); | |
663 message = SvPV(ST(1), junk); | |
5445
ad9b6e65713b
[gaim-migrate @ 5827]
Christian Hammond <chipx86@chipx86.com>
parents:
5436
diff
changeset
|
664 gaim_notify_info(my_plugin, NULL, title, message); |
5205 | 665 XSRETURN(0); |
666 } | |
667 | |
668 XS (XS_GAIM_buddy_list) | |
669 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
670 GaimConnection *gc; |
5205 | 671 struct buddy *buddy; |
672 struct group *g; | |
673 GaimBlistNode *gnode,*bnode; | |
674 int i = 0; | |
675 dXSARGS; | |
676 items = 0; | |
677 | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
678 gc = (GaimConnection *)SvIV(ST(0)); |
5205 | 679 |
680 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { | |
681 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
682 continue; | |
683 g = (struct group *)gnode; | |
684 for(bnode = gnode->child; bnode; bnode = bnode->next) { | |
685 if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) | |
686 continue; | |
687 buddy = (struct buddy *)bnode; | |
688 if(buddy->account == gc->account) | |
689 XST_mPV(i++, buddy->name); | |
690 } | |
691 } | |
692 XSRETURN(i); | |
693 } | |
694 | |
695 XS (XS_GAIM_online_list) | |
696 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
697 GaimConnection *gc; |
5205 | 698 struct buddy *b; |
699 struct group *g; | |
700 GaimBlistNode *gnode,*bnode; | |
701 int i = 0; | |
702 dXSARGS; | |
703 items = 0; | |
704 | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
705 gc = (GaimConnection *)SvIV(ST(0)); |
5205 | 706 |
707 for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { | |
708 if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) | |
709 continue; | |
710 g = (struct group *)gnode; | |
711 for(bnode = gnode->child; bnode; bnode = bnode->next) { | |
712 if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) | |
713 continue; | |
714 b = (struct buddy *)bnode; | |
715 if (b->account == gc->account && GAIM_BUDDY_IS_ONLINE(b)) XST_mPV(i++, b->name); | |
716 } | |
717 } | |
718 XSRETURN(i); | |
719 } | |
720 | |
721 XS (XS_GAIM_command) | |
722 { | |
723 unsigned int junk; | |
724 char *command = NULL; | |
725 dXSARGS; | |
726 items = 0; | |
727 | |
728 command = SvPV(ST(0), junk); | |
729 if (!command) XSRETURN(0); | |
730 if (!strncasecmp(command, "signon", 6)) { | |
731 int index = SvIV(ST(1)); | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
732 if (g_list_nth_data(gaim_accounts_get_all(), index)) |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
733 serv_login(g_list_nth_data(gaim_accounts_get_all(), index)); |
5205 | 734 } else if (!strncasecmp(command, "signoff", 7)) { |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
735 GaimConnection *gc = (GaimConnection *)SvIV(ST(1)); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
736 if (g_list_find(gaim_connections_get_all(), gc)) |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
737 gaim_connection_disconnect(gc); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
738 else |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
739 gaim_connections_disconnect_all(); |
5205 | 740 } else if (!strncasecmp(command, "info", 4)) { |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
741 GaimConnection *gc = (GaimConnection *)SvIV(ST(1)); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
742 if (g_list_find(gaim_connections_get_all(), gc)) |
5205 | 743 serv_set_info(gc, SvPV(ST(2), junk)); |
744 } else if (!strncasecmp(command, "away", 4)) { | |
745 char *message = SvPV(ST(1), junk); | |
746 static struct away_message a; | |
747 g_snprintf(a.message, sizeof(a.message), "%s", message); | |
748 do_away_message(NULL, &a); | |
749 } else if (!strncasecmp(command, "back", 4)) { | |
750 do_im_back(); | |
751 } else if (!strncasecmp(command, "idle", 4)) { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
752 GList *c = gaim_connections_get_all(); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
753 GaimConnection *gc; |
5205 | 754 |
755 while (c) { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
756 gc = (GaimConnection *)c->data; |
5205 | 757 serv_set_idle(gc, SvIV(ST(1))); |
758 c = c->next; | |
759 } | |
760 } else if (!strncasecmp(command, "warn", 4)) { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
761 GList *c = gaim_connections_get_all(); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
762 GaimConnection *gc; |
5205 | 763 |
764 while (c) { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
765 gc = (GaimConnection *)c->data; |
5205 | 766 serv_warn(gc, SvPV(ST(1), junk), SvIV(ST(2))); |
767 c = c->next; | |
768 } | |
769 } | |
770 | |
771 XSRETURN(0); | |
772 } | |
773 | |
774 XS (XS_GAIM_user_info) | |
775 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
776 GaimConnection *gc; |
5205 | 777 unsigned int junk; |
778 struct buddy *buddy = NULL; | |
779 dXSARGS; | |
780 items = 0; | |
781 | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
782 gc = (GaimConnection *)SvIV(ST(0)); |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
783 if (g_list_find(gaim_connections_get_all(), gc)) |
5205 | 784 buddy = gaim_find_buddy(gc->account, SvPV(ST(1), junk)); |
785 | |
786 if (!buddy) | |
787 XSRETURN(0); | |
788 XST_mPV(0, buddy->name); | |
789 XST_mPV(1, gaim_get_buddy_alias(buddy)); | |
790 XST_mPV(2, GAIM_BUDDY_IS_ONLINE(buddy) ? "Online" : "Offline"); | |
791 XST_mIV(3, buddy->evil); | |
792 XST_mIV(4, buddy->signon); | |
793 XST_mIV(5, buddy->idle); | |
794 XSRETURN(6); | |
795 } | |
796 | |
797 XS (XS_GAIM_write_to_conv) | |
798 { | |
799 char *nick, *who, *what; | |
800 struct gaim_conversation *c; | |
801 int junk; | |
802 int send, wflags; | |
803 dXSARGS; | |
804 items = 0; | |
805 | |
806 nick = SvPV(ST(0), junk); | |
807 send = SvIV(ST(1)); | |
808 what = SvPV(ST(2), junk); | |
809 who = SvPV(ST(3), junk); | |
810 | |
811 if (!*who) who=NULL; | |
812 | |
813 switch (send) { | |
814 case 0: wflags=WFLAG_SEND; break; | |
815 case 1: wflags=WFLAG_RECV; break; | |
816 case 2: wflags=WFLAG_SYSTEM; break; | |
817 default: wflags=WFLAG_RECV; | |
818 } | |
819 | |
820 c = gaim_find_conversation(nick); | |
821 | |
822 if (!c) | |
823 c = gaim_conversation_new(GAIM_CONV_IM, NULL, nick); | |
824 | |
825 gaim_conversation_write(c, who, what, -1, wflags, time(NULL)); | |
826 XSRETURN(0); | |
827 } | |
828 | |
829 XS (XS_GAIM_serv_send_im) | |
830 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
831 GaimConnection *gc; |
5205 | 832 char *nick, *what; |
833 int isauto; | |
834 int junk; | |
835 dXSARGS; | |
836 items = 0; | |
837 | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
838 gc = (GaimConnection *)SvIV(ST(0)); |
5205 | 839 nick = SvPV(ST(1), junk); |
840 what = SvPV(ST(2), junk); | |
841 isauto = SvIV(ST(3)); | |
842 | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
843 if (!g_list_find(gaim_connections_get_all(), gc)) { |
5205 | 844 XSRETURN(0); |
845 return; | |
846 } | |
847 serv_send_im(gc, nick, what, -1, isauto); | |
848 XSRETURN(0); | |
849 } | |
850 | |
851 XS (XS_GAIM_print_to_conv) | |
852 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
853 GaimConnection *gc; |
5205 | 854 char *nick, *what; |
855 int isauto; | |
856 struct gaim_conversation *c; | |
857 unsigned int junk; | |
858 dXSARGS; | |
859 items = 0; | |
860 | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
861 gc = (GaimConnection *)SvIV(ST(0)); |
5205 | 862 nick = SvPV(ST(1), junk); |
863 what = SvPV(ST(2), junk); | |
864 isauto = SvIV(ST(3)); | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
865 if (!g_list_find(gaim_connections_get_all(), gc)) { |
5205 | 866 XSRETURN(0); |
867 return; | |
868 } | |
869 | |
870 c = gaim_find_conversation(nick); | |
871 | |
872 if (!c) | |
873 c = gaim_conversation_new(GAIM_CONV_IM, gc->account, nick); | |
874 else | |
875 gaim_conversation_set_account(c, gc->account); | |
876 | |
877 gaim_conversation_write(c, NULL, what, -1, | |
878 (WFLAG_SEND | (isauto ? WFLAG_AUTO : 0)), time(NULL)); | |
879 serv_send_im(gc, nick, what, -1, isauto ? IM_FLAG_AWAY : 0); | |
880 XSRETURN(0); | |
881 } | |
882 | |
883 | |
884 | |
885 XS (XS_GAIM_print_to_chat) | |
886 { | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
887 GaimConnection *gc; |
5205 | 888 int id; |
889 char *what; | |
890 struct gaim_conversation *b = NULL; | |
891 GSList *bcs; | |
892 unsigned int junk; | |
893 dXSARGS; | |
894 items = 0; | |
895 | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
896 gc = (GaimConnection *)SvIV(ST(0)); |
5205 | 897 id = SvIV(ST(1)); |
898 what = SvPV(ST(2), junk); | |
899 | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
900 if (!g_list_find(gaim_connections_get_all(), gc)) { |
5205 | 901 XSRETURN(0); |
902 return; | |
903 } | |
904 bcs = gc->buddy_chats; | |
905 while (bcs) { | |
906 b = (struct gaim_conversation *)bcs->data; | |
907 | |
908 if (gaim_chat_get_id(gaim_conversation_get_chat_data(b)) == id) | |
909 break; | |
910 bcs = bcs->next; | |
911 b = NULL; | |
912 } | |
913 if (b) | |
914 serv_chat_send(gc, id, what); | |
915 XSRETURN(0); | |
916 } | |
917 | |
918 static int | |
919 perl_event(GaimEvent event, void *unused, va_list args) | |
920 { | |
921 char *buf[5] = { NULL, NULL, NULL, NULL, NULL }; /* Maximum of 5 args */ | |
922 void *arg1 = NULL, *arg2 = NULL, *arg3 = NULL, *arg4 = NULL, *arg5 = NULL; | |
923 char tmpbuf1[16], tmpbuf2[16], tmpbuf3[1]; | |
924 GList *handler; | |
925 struct _perl_event_handlers *data; | |
926 int handler_return; | |
927 | |
928 arg1 = va_arg(args, void *); | |
929 arg2 = va_arg(args, void *); | |
930 arg3 = va_arg(args, void *); | |
931 arg4 = va_arg(args, void *); | |
932 arg5 = va_arg(args, void *); | |
933 | |
934 tmpbuf1[0] = '\0'; | |
935 tmpbuf2[0] = '\0'; | |
936 tmpbuf3[0] = '\0'; | |
937 | |
938 /* Make a pretty array of char*'s with which to call perl functions */ | |
939 switch (event) { | |
5408
2af3224b329a
[gaim-migrate @ 5784]
Christian Hammond <chipx86@chipx86.com>
parents:
5227
diff
changeset
|
940 case event_connecting: |
5205 | 941 case event_signon: |
942 case event_signoff: | |
943 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
944 buf[0] = tmpbuf1; | |
945 break; | |
946 case event_away: | |
947 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
948 buf[0] = tmpbuf1; | |
5586
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
949 buf[1] = ((GaimConnection *)arg1)->away ? |
cde28f5c47d4
[gaim-migrate @ 5990]
Christian Hammond <chipx86@chipx86.com>
parents:
5470
diff
changeset
|
950 ((GaimConnection *)arg1)->away : tmpbuf2; |
5205 | 951 break; |
952 case event_im_recv: | |
953 if (!*(char**)arg2 || !*(char**)arg3) return 1; | |
954 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
955 buf[0] = tmpbuf1; | |
956 buf[1] = *(char **)arg2; | |
957 buf[2] = *(char **)arg3; | |
958 break; | |
959 case event_im_send: | |
960 if (!*(char**)arg3) return 1; | |
961 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
962 buf[0] = tmpbuf1; | |
963 buf[1] = arg2 ? arg2 : tmpbuf3; | |
964 buf[2] = *(char **)arg3; | |
965 break; | |
966 case event_buddy_signon: | |
967 case event_buddy_signoff: | |
968 case event_set_info: | |
969 case event_buddy_away: | |
970 case event_buddy_back: | |
971 case event_buddy_idle: | |
972 case event_buddy_unidle: | |
973 case event_got_typing: | |
974 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
975 buf[0] = tmpbuf1; | |
976 buf[1] = arg2; | |
977 break; | |
978 case event_chat_invited: | |
979 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
980 buf[0] = tmpbuf1; | |
981 buf[1] = arg2; | |
982 buf[2] = arg3; | |
983 buf[3] = arg4; | |
984 break; | |
985 case event_chat_join: | |
986 case event_chat_buddy_join: | |
987 case event_chat_buddy_leave: | |
988 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
989 buf[0] = tmpbuf1; | |
990 g_snprintf(tmpbuf2, 16, "%d", (int)arg2); | |
991 buf[1] = tmpbuf2; | |
992 buf[2] = arg3; | |
993 break; | |
994 case event_chat_leave: | |
995 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
996 buf[0] = tmpbuf1; | |
997 g_snprintf(tmpbuf2, 16, "%d", (int)arg2); | |
998 buf[1] = tmpbuf2; | |
999 break; | |
1000 case event_chat_recv: | |
1001 if (!*(char**)arg3 || !*(char**)arg4) return 1; | |
1002 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
1003 buf[0] = tmpbuf1; | |
1004 g_snprintf(tmpbuf2, 16, "%d", (int)arg2); | |
1005 buf[1] = tmpbuf2; | |
1006 buf[2] = *(char **)arg3; | |
1007 buf[3] = *(char **)arg4; | |
1008 break; | |
1009 case event_chat_send_invite: | |
1010 if (!*(char**)arg4) return 1; | |
1011 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
1012 buf[0] = tmpbuf1; | |
1013 g_snprintf(tmpbuf2, 16, "%d", (int)arg2); | |
1014 buf[1] = tmpbuf2; | |
1015 buf[2] = arg3; | |
1016 buf[3] = *(char **)arg4; | |
1017 break; | |
1018 case event_chat_send: | |
1019 if (!*(char**)arg3) return 1; | |
1020 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
1021 buf[0] = tmpbuf1; | |
1022 g_snprintf(tmpbuf2, 16, "%d", (int)arg2); | |
1023 buf[1] = tmpbuf2; | |
1024 buf[2] = *(char **)arg3; | |
1025 break; | |
1026 case event_warned: | |
1027 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
1028 buf[0] = tmpbuf1; | |
1029 buf[1] = arg2 ? arg2 : tmpbuf3; | |
1030 g_snprintf(tmpbuf2, 16, "%d", (int)arg3); | |
1031 buf[2] = tmpbuf2; | |
1032 break; | |
1033 case event_quit: | |
1034 case event_blist_update: | |
1035 buf[0] = tmpbuf3; | |
1036 break; | |
1037 case event_new_conversation: | |
1038 case event_del_conversation: | |
1039 buf[0] = arg1; | |
1040 break; | |
1041 case event_im_displayed_sent: | |
1042 if (!*(char**)arg3) return 1; | |
1043 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
1044 buf[0] = tmpbuf1; | |
1045 buf[1] = arg2; | |
1046 buf[2] = *(char **)arg3; | |
1047 break; | |
1048 case event_im_displayed_rcvd: | |
1049 g_snprintf(tmpbuf1, 16, "%lu", (unsigned long)arg1); | |
1050 buf[0] = tmpbuf1; | |
1051 buf[1] = arg2; | |
1052 buf[2] = arg3 ? arg3 : tmpbuf3; | |
1053 break; | |
1054 case event_draw_menu: | |
1055 /* we can't handle this usefully without gtk/perl bindings */ | |
1056 return 0; | |
1057 default: | |
5227
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1058 gaim_debug(GAIM_DEBUG_WARNING, "perl", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1059 "Someone forgot to handle %s in the perl binding\n", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1060 gaim_event_get_name(event)); |
5205 | 1061 return 0; |
1062 } | |
1063 | |
1064 /* Call any applicable functions */ | |
1065 for (handler = perl_event_handlers; | |
1066 handler != NULL; | |
1067 handler = handler->next) { | |
1068 | |
1069 data = handler->data; | |
1070 | |
1071 if (!strcmp(gaim_event_get_name(event), data->event_type)) { | |
1072 | |
1073 handler_return = execute_perl(data->handler_name, 5, buf); | |
1074 | |
1075 if (handler_return) | |
1076 return handler_return; | |
1077 } | |
1078 } | |
1079 | |
1080 /* Now make changes from perl scripts affect the real data */ | |
1081 switch (event) { | |
1082 case event_im_recv: | |
1083 if (buf[1] != *(char **)arg2) { | |
1084 free(*(char **)arg2); | |
1085 *(char **)arg2 = buf[1]; | |
1086 } | |
1087 if (buf[2] != *(char **)arg3) { | |
1088 free(*(char **)arg3); | |
1089 *(char **)arg3 = buf[2]; | |
1090 } | |
1091 break; | |
1092 case event_im_send: | |
1093 if (buf[2] != *(char **)arg3) { | |
1094 free(*(char **)arg3); | |
1095 *(char **)arg3 = buf[2]; | |
1096 } | |
1097 break; | |
1098 case event_chat_recv: | |
1099 if (buf[2] != *(char **)arg3) { | |
1100 free(*(char **)arg3); | |
1101 *(char **)arg3 = buf[2]; | |
1102 } | |
1103 if (buf[3] != *(char **)arg4) { | |
1104 free(*(char **)arg4); | |
1105 *(char **)arg4 = buf[3]; | |
1106 } | |
1107 break; | |
1108 case event_chat_send_invite: | |
1109 if (buf[3] != *(char **)arg4) { | |
1110 free(*(char **)arg4); | |
1111 *(char **)arg4 = buf[3]; | |
1112 } | |
1113 break; | |
1114 case event_chat_send: | |
1115 if (buf[2] != *(char **)arg3) { | |
1116 free(*(char **)arg3); | |
1117 *(char **)arg3 = buf[2]; | |
1118 } | |
1119 break; | |
1120 case event_im_displayed_sent: | |
1121 if (buf[2] != *(char **)arg3) { | |
1122 free(*(char **)arg3); | |
1123 *(char **)arg3 = buf[2]; | |
1124 } | |
1125 break; | |
1126 default: | |
1127 break; | |
1128 } | |
1129 | |
1130 return 0; | |
1131 } | |
1132 | |
1133 XS (XS_GAIM_add_event_handler) | |
1134 { | |
1135 unsigned int junk; | |
1136 struct _perl_event_handlers *handler; | |
1137 char *handle; | |
1138 GaimPlugin *plug; | |
1139 GList *p; | |
1140 dXSARGS; | |
1141 items = 0; | |
1142 | |
1143 handle = SvPV(ST(0), junk); | |
1144 | |
1145 for (p = gaim_plugins_get_all(); p != NULL; p = p->next) { | |
1146 plug = p->data; | |
1147 | |
1148 if (!strcmp(handle, plug->path)) | |
1149 break; | |
1150 } | |
1151 | |
1152 if (p) { | |
1153 handler = g_new0(struct _perl_event_handlers, 1); | |
1154 handler->event_type = g_strdup(SvPV(ST(1), junk)); | |
1155 handler->handler_name = g_strdup(SvPV(ST(2), junk)); | |
1156 handler->plug = plug; | |
1157 perl_event_handlers = g_list_append(perl_event_handlers, handler); | |
5227
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1158 gaim_debug(GAIM_DEBUG_INFO, "perl", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1159 "Registered perl event handler for %s\n", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1160 handler->event_type); |
5205 | 1161 } else { |
5227
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1162 gaim_debug(GAIM_DEBUG_ERROR, "perl", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1163 "Invalid handle (%s) registering perl event handler\n", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1164 handle); |
5205 | 1165 } |
1166 | |
1167 XSRETURN_EMPTY; | |
1168 } | |
1169 | |
1170 XS (XS_GAIM_remove_event_handler) | |
1171 { | |
1172 unsigned int junk; | |
1173 struct _perl_event_handlers *ehn; | |
1174 GList *cur = perl_event_handlers; | |
1175 dXSARGS; | |
1176 items = 0; | |
1177 | |
1178 while (cur) { | |
1179 GList *next = cur->next; | |
1180 ehn = cur->data; | |
1181 | |
1182 if (!strcmp(ehn->event_type, SvPV(ST(0), junk)) && | |
1183 !strcmp(ehn->handler_name, SvPV(ST(1), junk))) | |
1184 { | |
1185 perl_event_handlers = g_list_remove(perl_event_handlers, ehn); | |
1186 g_free(ehn->event_type); | |
1187 g_free(ehn->handler_name); | |
1188 g_free(ehn); | |
1189 } | |
1190 | |
1191 cur = next; | |
1192 } | |
1193 } | |
1194 | |
1195 static int | |
1196 perl_timeout(gpointer data) | |
1197 { | |
1198 char *atmp[2] = { NULL, NULL }; | |
1199 struct _perl_timeout_handlers *handler = data; | |
1200 | |
1201 atmp[0] = escape_quotes(handler->handler_args); | |
1202 execute_perl(handler->handler_name, 1, atmp); | |
1203 | |
1204 perl_timeout_handlers = g_list_remove(perl_timeout_handlers, handler); | |
1205 g_free(handler->handler_args); | |
1206 g_free(handler->handler_name); | |
1207 g_free(handler); | |
1208 | |
1209 return 0; /* returning zero removes the timeout handler */ | |
1210 } | |
1211 | |
1212 XS (XS_GAIM_add_timeout_handler) | |
1213 { | |
1214 unsigned int junk; | |
1215 long timeout; | |
1216 struct _perl_timeout_handlers *handler; | |
1217 char *handle; | |
1218 GaimPlugin *plug; | |
1219 GList *p; | |
1220 | |
1221 dXSARGS; | |
1222 items = 0; | |
1223 | |
1224 handle = SvPV(ST(0), junk); | |
1225 | |
1226 for (p = gaim_plugins_get_all(); p != NULL; p = p->next) { | |
1227 plug = p->data; | |
1228 | |
1229 if (!strcmp(handle, plug->path)) | |
1230 break; | |
1231 } | |
1232 | |
1233 if (p) { | |
1234 handler = g_new0(struct _perl_timeout_handlers, 1); | |
1235 timeout = 1000 * SvIV(ST(1)); | |
5227
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1236 gaim_debug(GAIM_DEBUG_INFO, "perl", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1237 "Adding timeout for %ld seconds.\n", timeout/1000); |
5205 | 1238 handler->plug = plug; |
1239 handler->handler_name = g_strdup(SvPV(ST(2), junk)); | |
1240 handler->handler_args = g_strdup(SvPV(ST(3), junk)); | |
1241 perl_timeout_handlers = g_list_append(perl_timeout_handlers, handler); | |
1242 handler->iotag = g_timeout_add(timeout, perl_timeout, handler); | |
1243 } else { | |
5227
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1244 gaim_debug(GAIM_DEBUG_ERROR, "perl", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1245 "Invalid handle (%s) in adding perl timeout handler.", |
6d1707dc8c3d
[gaim-migrate @ 5597]
Christian Hammond <chipx86@chipx86.com>
parents:
5205
diff
changeset
|
1246 handle); |
5205 | 1247 } |
1248 XSRETURN_EMPTY; | |
1249 } | |
1250 | |
1251 XS (XS_GAIM_play_sound) | |
1252 { | |
1253 int id; | |
1254 dXSARGS; | |
1255 | |
1256 items = 0; | |
1257 | |
1258 id = SvIV(ST(0)); | |
1259 | |
1260 gaim_sound_play_event(id); | |
1261 | |
1262 XSRETURN_EMPTY; | |
1263 } | |
1264 | |
1265 static gboolean | |
1266 probe_perl_plugin(GaimPlugin *plugin) | |
1267 { | |
1268 /* XXX This would be much faster if I didn't create a new | |
1269 * PerlInterpreter every time I probed a plugin */ | |
1270 | |
1271 GaimPluginInfo *info; | |
1272 PerlInterpreter *prober = perl_alloc(); | |
1273 char *argv[] = {"", plugin->path }; | |
1274 int count; | |
1275 gboolean status = TRUE; | |
1276 | |
1277 perl_construct(prober); | |
1278 perl_parse(prober, NULL, 2, argv, NULL); | |
1279 | |
1280 { | |
1281 dSP; | |
1282 ENTER; | |
1283 SAVETMPS; | |
1284 PUSHMARK(SP); | |
1285 | |
1286 count = perl_call_pv("description", G_NOARGS | G_ARRAY | G_EVAL); | |
1287 SPAGAIN; | |
1288 | |
1289 if (count == 6) { | |
1290 info = g_new0(GaimPluginInfo, 1); | |
1291 | |
1292 info->api_version = 2; | |
1293 info->type = GAIM_PLUGIN_STANDARD; | |
1294 | |
1295 info->dependencies = g_list_append(info->dependencies, | |
1296 PERL_PLUGIN_ID); | |
1297 | |
1298 POPp; /* iconfile */ | |
1299 | |
1300 info->homepage = g_strdup(POPp); | |
1301 info->author = g_strdup(POPp); | |
1302 info->description = g_strdup(POPp); | |
1303 info->version = g_strdup(POPp); | |
1304 info->name = g_strdup(POPp); | |
1305 | |
1306 plugin->info = info; | |
1307 | |
1308 if (!gaim_plugin_register(plugin)) | |
1309 status = FALSE; | |
1310 } | |
1311 else | |
1312 status = FALSE; | |
1313 | |
1314 PUTBACK; | |
1315 FREETMPS; | |
1316 LEAVE; | |
1317 } | |
1318 | |
1319 perl_destruct(prober); | |
1320 perl_free(prober); | |
1321 | |
1322 return status; | |
1323 } | |
1324 | |
1325 static gboolean | |
1326 load_perl_plugin(GaimPlugin *plugin) | |
1327 { | |
1328 perl_load_file(plugin->path, plugin); | |
1329 | |
1330 return TRUE; | |
1331 } | |
1332 | |
1333 static gboolean | |
1334 unload_perl_plugin(GaimPlugin *plugin) | |
1335 { | |
1336 perl_unload_file(plugin); | |
1337 | |
1338 return TRUE; | |
1339 } | |
1340 | |
1341 static void | |
1342 destroy_perl_plugin(GaimPlugin *plugin) | |
1343 { | |
1344 if (plugin->info != NULL) { | |
1345 g_free(plugin->info->name); | |
1346 g_free(plugin->info->version); | |
1347 g_free(plugin->info->description); | |
1348 g_free(plugin->info->author); | |
1349 g_free(plugin->info->homepage); | |
1350 } | |
1351 } | |
1352 | |
1353 static gboolean | |
1354 plugin_unload(GaimPlugin *plugin) | |
1355 { | |
1356 perl_end(); | |
1357 | |
1358 return TRUE; | |
1359 } | |
1360 | |
1361 static GaimPluginLoaderInfo loader_info = | |
1362 { | |
1363 NULL, /**< exts */ | |
1364 | |
1365 probe_perl_plugin, /**< probe */ | |
1366 load_perl_plugin, /**< load */ | |
1367 unload_perl_plugin, /**< unload */ | |
1368 destroy_perl_plugin, /**< destroy */ | |
1369 perl_event /**< broadcast */ | |
1370 }; | |
1371 | |
1372 static GaimPluginInfo info = | |
1373 { | |
1374 2, /**< api_version */ | |
1375 GAIM_PLUGIN_LOADER, /**< type */ | |
1376 NULL, /**< ui_requirement */ | |
1377 0, /**< flags */ | |
1378 NULL, /**< dependencies */ | |
1379 GAIM_PRIORITY_DEFAULT, /**< priority */ | |
1380 | |
1381 PERL_PLUGIN_ID, /**< id */ | |
1382 N_("Perl Plugin Loader"), /**< name */ | |
1383 VERSION, /**< version */ | |
1384 N_("Provides support for loading perl plugins."), /**< summary */ | |
1385 N_("Provides support for loading perl plugins."), /**< description */ | |
1386 "Christian Hammond <chipx86@gnupdate.org>", /**< author */ | |
1387 WEBSITE, /**< homepage */ | |
1388 | |
1389 NULL, /**< load */ | |
1390 plugin_unload, /**< unload */ | |
1391 NULL, /**< destroy */ | |
1392 | |
1393 NULL, /**< ui_info */ | |
1394 &loader_info /**< extra_info */ | |
1395 }; | |
1396 | |
1397 static void | |
1398 __init_plugin(GaimPlugin *plugin) | |
1399 { | |
5436
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5408
diff
changeset
|
1400 my_plugin = plugin; |
ad445074d239
[gaim-migrate @ 5818]
Christian Hammond <chipx86@chipx86.com>
parents:
5408
diff
changeset
|
1401 |
5205 | 1402 loader_info.exts = g_list_append(loader_info.exts, "pl"); |
1403 } | |
1404 | |
1405 GAIM_INIT_PLUGIN(perl, __init_plugin, info); |