Mercurial > pidgin
annotate libgaim/protocols/irc/cmds.c @ 14482:a5c7db7be826
[gaim-migrate @ 17201]
Prevent irc accounts from being disconnected for long periods without us noticing. Use the prpl keepalive cb to ping the server if we haven't received anything in at least 60 seconds.
committer: Tailor Script <tailor@pidgin.im>
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Sat, 09 Sep 2006 19:39:31 +0000 |
parents | 60b1bc8dbf37 |
children |
rev | line source |
---|---|
14192 | 1 /** |
2 * @file cmds.c | |
14482
a5c7db7be826
[gaim-migrate @ 17201]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
3 * |
14192 | 4 * gaim |
5 * | |
6 * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu> | |
14482
a5c7db7be826
[gaim-migrate @ 17201]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
7 * |
14192 | 8 * This program is free software; you can redistribute it and/or modify |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 */ | |
22 | |
23 #include "internal.h" | |
24 | |
25 #include "conversation.h" | |
26 #include "debug.h" | |
27 #include "notify.h" | |
28 #include "util.h" | |
29 | |
30 #include "irc.h" | |
31 | |
32 | |
33 static void irc_do_mode(struct irc_conn *irc, const char *target, const char *sign, char **ops); | |
34 | |
35 int irc_cmd_default(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
36 { | |
37 GaimConversation *convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY, target, irc->account); | |
38 char *buf; | |
39 | |
40 if (!convo) | |
41 return 1; | |
42 | |
43 buf = g_strdup_printf(_("Unknown command: %s"), cmd); | |
44 if (gaim_conversation_get_type(convo) == GAIM_CONV_TYPE_IM) | |
45 gaim_conv_im_write(GAIM_CONV_IM(convo), "", buf, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); | |
46 else | |
47 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), "", buf, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); | |
48 g_free(buf); | |
49 | |
50 return 1; | |
51 } | |
52 | |
53 int irc_cmd_away(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
54 { | |
55 char *buf, *message; | |
56 | |
57 if (args[0] && strcmp(cmd, "back")) { | |
58 message = gaim_markup_strip_html(args[0]); | |
59 gaim_util_chrreplace(message, '\n', ' '); | |
60 buf = irc_format(irc, "v:", "AWAY", message); | |
61 g_free(message); | |
62 } else { | |
63 buf = irc_format(irc, "v", "AWAY"); | |
64 } | |
65 irc_send(irc, buf); | |
66 g_free(buf); | |
67 | |
68 return 0; | |
69 } | |
70 | |
71 int irc_cmd_ctcp_action(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
72 { | |
73 GaimConnection *gc = gaim_account_get_connection(irc->account); | |
74 char *action, *escaped, *dst, **newargs; | |
75 const char *src; | |
76 GaimConversation *convo; | |
77 | |
78 if (!args || !args[0] || !gc) | |
79 return 0; | |
80 | |
81 action = g_malloc(strlen(args[0]) + 10); | |
82 | |
83 sprintf(action, "\001ACTION "); | |
84 | |
85 src = args[0]; | |
86 dst = action + 8; | |
87 while (*src) { | |
88 if (*src == '\n') { | |
89 if (*(src + 1) == '\0') { | |
90 break; | |
91 } else { | |
92 *dst++ = ' '; | |
93 src++; | |
94 continue; | |
95 } | |
96 } | |
97 *dst++ = *src++; | |
98 } | |
99 *dst++ = '\001'; | |
100 *dst = '\0'; | |
101 | |
102 newargs = g_new0(char *, 2); | |
103 newargs[0] = g_strdup(target); | |
104 newargs[1] = action; | |
105 irc_cmd_privmsg(irc, cmd, target, (const char **)newargs); | |
106 g_free(newargs[0]); | |
107 g_free(newargs[1]); | |
108 g_free(newargs); | |
109 | |
110 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY, target, irc->account); | |
111 if (convo) { | |
112 escaped = g_markup_escape_text(args[0], -1); | |
113 action = g_strdup_printf("/me %s", escaped); | |
114 g_free(escaped); | |
115 if (action[strlen(action) - 1] == '\n') | |
116 action[strlen(action) - 1] = '\0'; | |
117 if (gaim_conversation_get_type(convo) == GAIM_CONV_TYPE_CHAT) | |
118 serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(convo)), | |
119 gaim_connection_get_display_name(gc), | |
120 0, action, time(NULL)); | |
121 else | |
122 gaim_conv_im_write(GAIM_CONV_IM(convo), gaim_connection_get_display_name(gc), | |
123 action, 0, time(NULL)); | |
124 g_free(action); | |
125 } | |
126 | |
127 return 1; | |
128 } | |
129 | |
130 int irc_cmd_ctcp_version(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
131 { | |
132 char *buf; | |
133 | |
134 | |
135 if (!args || !args[0]) | |
136 return 0; | |
137 | |
138 buf = irc_format(irc, "vn:", "PRIVMSG", args[0], "\001VERSION\001"); | |
139 irc_send(irc, buf); | |
140 g_free(buf); | |
141 | |
142 return 0; | |
143 } | |
144 | |
145 int irc_cmd_invite(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
146 { | |
147 char *buf; | |
148 | |
149 if (!args || !args[0] || !(args[1] || target)) | |
150 return 0; | |
151 | |
152 buf = irc_format(irc, "vnc", "INVITE", args[0], args[1] ? args[1] : target); | |
153 irc_send(irc, buf); | |
154 g_free(buf); | |
155 | |
156 return 0; | |
157 } | |
158 | |
159 int irc_cmd_join(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
160 { | |
161 char *buf; | |
162 | |
163 if (!args || !args[0]) | |
164 return 0; | |
165 | |
166 if (args[1]) | |
167 buf = irc_format(irc, "vcv", "JOIN", args[0], args[1]); | |
168 else | |
169 buf = irc_format(irc, "vc", "JOIN", args[0]); | |
170 irc_send(irc, buf); | |
171 g_free(buf); | |
172 | |
173 return 0; | |
174 } | |
175 | |
176 int irc_cmd_kick(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
177 { | |
178 char *buf; | |
179 GaimConversation *convo; | |
180 | |
181 if (!args || !args[0]) | |
182 return 0; | |
183 | |
184 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, target, irc->account); | |
185 if (!convo) | |
186 return 0; | |
187 | |
188 if (args[1]) | |
189 buf = irc_format(irc, "vcn:", "KICK", target, args[0], args[1]); | |
190 else | |
191 buf = irc_format(irc, "vcn", "KICK", target, args[0]); | |
192 irc_send(irc, buf); | |
193 g_free(buf); | |
194 | |
195 return 0; | |
196 } | |
197 | |
198 int irc_cmd_list(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
199 { | |
200 gaim_roomlist_show_with_account(irc->account); | |
201 | |
202 return 0; | |
203 } | |
204 | |
205 int irc_cmd_mode(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
206 { | |
207 GaimConnection *gc; | |
208 char *buf; | |
209 | |
210 if (!args) | |
211 return 0; | |
212 | |
213 if (!strcmp(cmd, "mode")) { | |
214 if (!args[0] && irc_ischannel(target)) | |
215 buf = irc_format(irc, "vc", "MODE", target); | |
216 else if (args[0] && (*args[0] == '+' || *args[0] == '-')) | |
217 buf = irc_format(irc, "vcv", "MODE", target, args[0]); | |
218 else if (args[0]) | |
219 buf = irc_format(irc, "vv", "MODE", args[0]); | |
220 else | |
221 return 0; | |
222 } else if (!strcmp(cmd, "umode")) { | |
223 if (!args[0]) | |
224 return 0; | |
225 gc = gaim_account_get_connection(irc->account); | |
226 buf = irc_format(irc, "vnv", "MODE", gaim_connection_get_display_name(gc), args[0]); | |
227 } else { | |
228 return 0; | |
229 } | |
230 | |
231 irc_send(irc, buf); | |
232 g_free(buf); | |
233 | |
234 return 0; | |
235 } | |
236 | |
237 int irc_cmd_names(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
238 { | |
239 char *buf; | |
240 | |
241 if (!args || (!args[0] && !irc_ischannel(target))) | |
242 return 0; | |
243 | |
244 buf = irc_format(irc, "vc", "NAMES", args[0] ? args[0] : target); | |
245 irc_send(irc, buf); | |
246 g_free(buf); | |
247 | |
248 irc->nameconv = g_strdup(target); | |
249 | |
250 return 0; | |
251 } | |
252 | |
253 int irc_cmd_nick(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
254 { | |
255 char *buf; | |
256 | |
257 if (!args || !args[0]) | |
258 return 0; | |
259 | |
260 buf = irc_format(irc, "v:", "NICK", args[0]); | |
261 irc_send(irc, buf); | |
262 g_free(buf); | |
263 | |
264 return 0; | |
265 } | |
266 | |
267 int irc_cmd_op(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
268 { | |
269 char **nicks, **ops, *sign, *mode; | |
270 int i = 0, used = 0; | |
271 | |
272 if (!args || !args[0] || !*args[0]) | |
273 return 0; | |
274 | |
275 if (!strcmp(cmd, "op")) { | |
276 sign = "+"; | |
277 mode = "o"; | |
278 } else if (!strcmp(cmd, "deop")) { | |
279 sign = "-"; | |
280 mode = "o"; | |
281 } else if (!strcmp(cmd, "voice")) { | |
282 sign = "+"; | |
283 mode = "v"; | |
284 } else if (!strcmp(cmd, "devoice")) { | |
285 sign = "-"; | |
286 mode = "v"; | |
287 } else { | |
288 gaim_debug(GAIM_DEBUG_ERROR, "irc", "invalid 'op' command '%s'\n", cmd); | |
289 return 0; | |
290 } | |
291 | |
292 nicks = g_strsplit(args[0], " ", -1); | |
293 | |
294 for (i = 0; nicks[i]; i++) | |
295 /* nothing */; | |
296 ops = g_new0(char *, i * 2 + 1); | |
297 | |
298 for (i = 0; nicks[i]; i++) { | |
299 if (!*nicks[i]) | |
300 continue; | |
301 ops[used++] = mode; | |
302 ops[used++] = nicks[i]; | |
303 } | |
304 | |
305 irc_do_mode(irc, target, sign, ops); | |
306 g_free(ops); | |
307 | |
308 return 0; | |
309 } | |
310 | |
311 int irc_cmd_part(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
312 { | |
313 char *buf; | |
314 | |
315 if (!args) | |
316 return 0; | |
317 | |
318 if (args[1]) | |
319 buf = irc_format(irc, "vc:", "PART", args[0] ? args[0] : target, args[1]); | |
320 else | |
321 buf = irc_format(irc, "vc", "PART", args[0] ? args[0] : target); | |
322 irc_send(irc, buf); | |
323 g_free(buf); | |
324 | |
325 return 0; | |
326 } | |
327 | |
328 int irc_cmd_ping(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
329 { | |
330 char *stamp; | |
331 char *buf; | |
332 | |
333 if (args && args[0]) { | |
334 if (irc_ischannel(args[0])) | |
335 return 0; | |
336 stamp = g_strdup_printf("\001PING %lu\001", time(NULL)); | |
337 buf = irc_format(irc, "vn:", "PRIVMSG", args[0], stamp); | |
338 g_free(stamp); | |
14482
a5c7db7be826
[gaim-migrate @ 17201]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
339 } else if (target) { |
14192 | 340 stamp = g_strdup_printf("%s %lu", target, time(NULL)); |
341 buf = irc_format(irc, "v:", "PING", stamp); | |
342 g_free(stamp); | |
14482
a5c7db7be826
[gaim-migrate @ 17201]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
343 } else { |
a5c7db7be826
[gaim-migrate @ 17201]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
344 stamp = g_strdup_printf("%lu", time(NULL)); |
a5c7db7be826
[gaim-migrate @ 17201]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
345 buf = irc_format(irc, "vv", "PING", stamp); |
a5c7db7be826
[gaim-migrate @ 17201]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
346 g_free(stamp); |
14192 | 347 } |
348 irc_send(irc, buf); | |
349 g_free(buf); | |
350 | |
351 return 0; | |
352 } | |
353 | |
354 int irc_cmd_privmsg(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
355 { | |
356 const char *cur, *end; | |
357 char *msg, *buf; | |
358 | |
359 if (!args || !args[0] || !args[1]) | |
360 return 0; | |
361 | |
362 cur = args[1]; | |
363 end = args[1]; | |
364 while (*end && *cur) { | |
365 end = strchr(cur, '\n'); | |
366 if (!end) | |
367 end = cur + strlen(cur); | |
368 msg = g_strndup(cur, end - cur); | |
369 buf = irc_format(irc, "vt:", "PRIVMSG", args[0], msg); | |
370 irc_send(irc, buf); | |
371 g_free(msg); | |
372 g_free(buf); | |
373 cur = end + 1; | |
374 } | |
375 | |
376 return 0; | |
377 } | |
378 | |
379 int irc_cmd_quit(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
380 { | |
381 char *buf; | |
382 | |
383 if (!irc->quitting) { | |
384 /* | |
385 * Use gaim_account_get_string(irc->account, "quitmsg", IRC_DEFAULT_QUIT) | |
386 * and uncomment the appropriate account preference in irc.c if we | |
387 * decide we want custom quit messages. | |
388 */ | |
389 buf = irc_format(irc, "v:", "QUIT", (args && args[0]) ? args[0] : IRC_DEFAULT_QUIT); | |
390 irc_send(irc, buf); | |
391 g_free(buf); | |
392 | |
393 irc->quitting = TRUE; | |
394 | |
395 if (!irc->account->disconnecting) | |
396 gaim_account_set_status(irc->account, "offline", TRUE, NULL); | |
397 } | |
398 | |
399 return 0; | |
400 } | |
401 | |
402 int irc_cmd_quote(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
403 { | |
404 char *buf; | |
405 | |
406 if (!args || !args[0]) | |
407 return 0; | |
408 | |
409 buf = irc_format(irc, "v", args[0]); | |
410 irc_send(irc, buf); | |
411 g_free(buf); | |
412 | |
413 return 0; | |
414 } | |
415 | |
416 int irc_cmd_query(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
417 { | |
418 GaimConversation *convo; | |
419 GaimConnection *gc; | |
420 | |
421 if (!args || !args[0]) | |
422 return 0; | |
423 | |
424 convo = gaim_conversation_new(GAIM_CONV_TYPE_IM, irc->account, args[0]); | |
425 gaim_conversation_present(convo); | |
426 | |
427 if (args[1]) { | |
428 gc = gaim_account_get_connection(irc->account); | |
429 irc_cmd_privmsg(irc, cmd, target, args); | |
430 gaim_conv_im_write(GAIM_CONV_IM(convo), gaim_connection_get_display_name(gc), | |
431 args[1], GAIM_MESSAGE_SEND, time(NULL)); | |
432 } | |
433 | |
434 return 0; | |
435 } | |
436 | |
437 int irc_cmd_remove(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
438 { | |
439 char *buf; | |
440 | |
441 if (!args || !args[0]) | |
442 return 0; | |
443 | |
444 if (!irc_ischannel(target)) /* not a channel, punt */ | |
445 return 0; | |
446 | |
447 if (args[1]) | |
448 buf = irc_format(irc, "vcn:", "REMOVE", target, args[0], args[1]); | |
449 else | |
450 buf = irc_format(irc, "vcn", "REMOVE", target, args[0]); | |
451 irc_send(irc, buf); | |
452 g_free(buf); | |
453 | |
454 return 0; | |
455 } | |
456 | |
457 int irc_cmd_service(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
458 { | |
459 char *capital_cmd, *buf; | |
460 | |
461 if (!args || !args[0]) | |
462 return 0; | |
463 | |
464 /* cmd will be one of nickserv, chanserv, memoserv or operserv */ | |
465 capital_cmd = g_ascii_strup(cmd, -1); | |
466 buf = irc_format(irc, "v:", capital_cmd, args[0]); | |
467 irc_send(irc, buf); | |
468 g_free(capital_cmd); | |
469 g_free(buf); | |
470 | |
471 return 0; | |
472 } | |
473 | |
474 int irc_cmd_time(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
475 { | |
476 char *buf; | |
477 | |
478 buf = irc_format(irc, "v", "TIME"); | |
479 irc_send(irc, buf); | |
480 g_free(buf); | |
481 | |
482 return 0; | |
483 } | |
484 | |
485 int irc_cmd_topic(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
486 { | |
487 char *buf; | |
488 const char *topic; | |
489 GaimConversation *convo; | |
490 | |
491 if (!args) | |
492 return 0; | |
493 | |
494 convo = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, target, irc->account); | |
495 if (!convo) | |
496 return 0; | |
497 | |
498 if (!args[0]) { | |
499 topic = gaim_conv_chat_get_topic (GAIM_CONV_CHAT(convo)); | |
500 | |
501 if (topic) { | |
502 char *tmp, *tmp2; | |
503 tmp = g_markup_escape_text(topic, -1); | |
504 tmp2 = gaim_markup_linkify(tmp); | |
505 buf = g_strdup_printf(_("current topic is: %s"), tmp2); | |
506 g_free(tmp); | |
507 g_free(tmp2); | |
508 } else | |
509 buf = g_strdup(_("No topic is set")); | |
510 gaim_conv_chat_write(GAIM_CONV_CHAT(convo), target, buf, GAIM_MESSAGE_SYSTEM|GAIM_MESSAGE_NO_LOG, time(NULL)); | |
511 g_free(buf); | |
512 | |
513 return 0; | |
514 } | |
515 | |
516 buf = irc_format(irc, "vt:", "TOPIC", target, args[0]); | |
517 irc_send(irc, buf); | |
518 g_free(buf); | |
519 | |
520 return 0; | |
521 } | |
522 | |
523 int irc_cmd_wallops(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
524 { | |
525 char *buf; | |
526 | |
527 if (!args || !args[0]) | |
528 return 0; | |
529 | |
530 if (!strcmp(cmd, "wallops")) | |
531 buf = irc_format(irc, "v:", "WALLOPS", args[0]); | |
532 else if (!strcmp(cmd, "operwall")) | |
533 buf = irc_format(irc, "v:", "OPERWALL", args[0]); | |
534 else | |
535 return 0; | |
536 | |
537 irc_send(irc, buf); | |
538 g_free(buf); | |
539 | |
540 return 0; | |
541 } | |
542 | |
543 int irc_cmd_whois(struct irc_conn *irc, const char *cmd, const char *target, const char **args) | |
544 { | |
545 char *buf; | |
546 | |
547 if (!args || !args[0]) | |
548 return 0; | |
549 | |
550 if (args[1]) { | |
551 buf = irc_format(irc, "vvn", "WHOIS", args[0], args[1]); | |
552 irc->whois.nick = g_strdup(args[1]); | |
553 } else { | |
554 buf = irc_format(irc, "vn", "WHOIS", args[0]); | |
555 irc->whois.nick = g_strdup(args[0]); | |
556 } | |
557 | |
558 irc_send(irc, buf); | |
559 g_free(buf); | |
560 | |
561 return 0; | |
562 } | |
563 | |
564 static void irc_do_mode(struct irc_conn *irc, const char *target, const char *sign, char **ops) | |
565 { | |
566 char *buf, mode[5]; | |
567 int i = 0; | |
568 | |
569 if (!sign) | |
570 return; | |
571 | |
572 while (ops[i]) { | |
573 if (ops[i + 2] && ops[i + 4]) { | |
574 g_snprintf(mode, sizeof(mode), "%s%s%s%s", sign, | |
575 ops[i], ops[i + 2], ops[i + 4]); | |
576 buf = irc_format(irc, "vcvnnn", "MODE", target, mode, | |
577 ops[i + 1], ops[i + 3], ops[i + 5]); | |
578 i += 6; | |
579 } else if (ops[i + 2]) { | |
580 g_snprintf(mode, sizeof(mode), "%s%s%s", | |
581 sign, ops[i], ops[i + 2]); | |
582 buf = irc_format(irc, "vcvnn", "MODE", target, mode, | |
583 ops[i + 1], ops[i + 3]); | |
584 i += 4; | |
585 } else { | |
586 g_snprintf(mode, sizeof(mode), "%s%s", sign, ops[i]); | |
587 buf = irc_format(irc, "vcvn", "MODE", target, mode, ops[i + 1]); | |
588 i += 2; | |
589 } | |
590 irc_send(irc, buf); | |
591 g_free(buf); | |
592 } | |
593 | |
594 return; | |
595 } |