| |
1 /** |
| |
2 * @file cmds.c |
| |
3 * |
| |
4 * gaim |
| |
5 * |
| |
6 * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu> |
| |
7 * |
| |
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 "notify.h" |
| |
27 #include "debug.h" |
| |
28 #include "irc.h" |
| |
29 |
| |
30 |
| |
31 static void irc_do_mode(struct irc_conn *irc, const char *target, const char *sign, char **ops); |
| |
32 |
| |
33 int irc_cmd_default(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
34 { |
| |
35 GaimConversation *convo = gaim_find_conversation_with_account(target, irc->account); |
| |
36 char *buf; |
| |
37 |
| |
38 if (!convo) |
| |
39 return; |
| |
40 |
| |
41 buf = g_strdup_printf(_("Unknown command: %s"), cmd); |
| |
42 if (gaim_conversation_get_type(convo) == GAIM_CONV_IM) |
| |
43 gaim_im_write(GAIM_IM(convo), "", buf, -1, WFLAG_SYSTEM|WFLAG_NOLOG, time(NULL)); |
| |
44 else |
| |
45 gaim_chat_write(GAIM_CHAT(convo), "", buf, WFLAG_SYSTEM|WFLAG_NOLOG, time(NULL)); |
| |
46 g_free(buf); |
| |
47 |
| |
48 return 1; |
| |
49 } |
| |
50 |
| |
51 int irc_cmd_away(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
52 { |
| |
53 char *buf, *message, *cur; |
| |
54 |
| |
55 if (args[0] && strcmp(cmd, "back")) { |
| |
56 message = strdup(args[0]); |
| |
57 for (cur = message; *cur; cur++) { |
| |
58 if (*cur == '\n') |
| |
59 *cur = ' '; |
| |
60 } |
| |
61 buf = irc_format(irc, "v:", "AWAY", message); |
| |
62 g_free(message); |
| |
63 } else { |
| |
64 buf = irc_format(irc, "v", "AWAY"); |
| |
65 } |
| |
66 irc_send(irc, buf); |
| |
67 g_free(buf); |
| |
68 |
| |
69 return 0; |
| |
70 } |
| |
71 |
| |
72 int irc_cmd_ctcp_action(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
73 { |
| |
74 GaimConnection *gc = gaim_account_get_connection(irc->account); |
| |
75 char *action, *dst, **newargs; |
| |
76 const char *src; |
| |
77 GaimConversation *convo; |
| |
78 |
| |
79 if (!args || !args[0] || !gc) |
| |
80 return 0; |
| |
81 |
| |
82 action = g_malloc(strlen(args[0]) + 9); |
| |
83 |
| |
84 sprintf(action, "\001ACTION "); |
| |
85 |
| |
86 src = args[0]; |
| |
87 dst = action + 8; |
| |
88 while (*src) { |
| |
89 if (*src == '\n') { |
| |
90 if (*(src + 1) == '\0') { |
| |
91 break; |
| |
92 } else { |
| |
93 *dst++ = ' '; |
| |
94 src++; |
| |
95 continue; |
| |
96 } |
| |
97 } |
| |
98 *dst++ = *src++; |
| |
99 } |
| |
100 *dst++ = '\001'; |
| |
101 *dst = '\0'; |
| |
102 |
| |
103 newargs = g_new0(char *, 2); |
| |
104 newargs[0] = g_strdup(target); |
| |
105 newargs[1] = action; |
| |
106 irc_cmd_privmsg(irc, cmd, target, (const char **)newargs); |
| |
107 g_free(newargs[0]); |
| |
108 g_free(newargs[1]); |
| |
109 g_free(newargs); |
| |
110 |
| |
111 convo = gaim_find_conversation_with_account(target, irc->account); |
| |
112 if (convo && gaim_conversation_get_type(convo) == GAIM_CONV_CHAT) { |
| |
113 action = g_strdup_printf("/me %s", args[0]); |
| |
114 if (action[strlen(action) - 1] == '\n') |
| |
115 action[strlen(action) - 1] = '\0'; |
| |
116 serv_got_chat_in(gc, gaim_chat_get_id(GAIM_CHAT(convo)), |
| |
117 gaim_connection_get_display_name(gc), |
| |
118 0, action, time(NULL)); |
| |
119 g_free(action); |
| |
120 } |
| |
121 |
| |
122 return 1; |
| |
123 } |
| |
124 |
| |
125 int irc_cmd_invite(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
126 { |
| |
127 char *buf; |
| |
128 |
| |
129 if (!args || !args[0] || !(args[1] || target)) |
| |
130 return 0; |
| |
131 |
| |
132 buf = irc_format(irc, "vnc", "INVITE", args[0], args[1] ? args[1] : target); |
| |
133 irc_send(irc, buf); |
| |
134 g_free(buf); |
| |
135 |
| |
136 return 0; |
| |
137 } |
| |
138 |
| |
139 int irc_cmd_join(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
140 { |
| |
141 char *buf; |
| |
142 |
| |
143 if (!args || !args[0]) |
| |
144 return 0; |
| |
145 |
| |
146 if (args[1]) |
| |
147 buf = irc_format(irc, "vcv", "JOIN", args[0], args[1]); |
| |
148 else |
| |
149 buf = irc_format(irc, "vc", "JOIN", args[0]); |
| |
150 irc_send(irc, buf); |
| |
151 g_free(buf); |
| |
152 |
| |
153 return 0; |
| |
154 } |
| |
155 |
| |
156 int irc_cmd_kick(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
157 { |
| |
158 char *buf; |
| |
159 GaimConversation *convo; |
| |
160 |
| |
161 if (!args || !args[0]) |
| |
162 return 0; |
| |
163 |
| |
164 convo = gaim_find_conversation_with_account(target, irc->account); |
| |
165 if (!convo || gaim_conversation_get_type(convo) != GAIM_CONV_CHAT) |
| |
166 return; |
| |
167 |
| |
168 if (args[1]) |
| |
169 buf = irc_format(irc, "vcn:", "KICK", target, args[0], args[1]); |
| |
170 else |
| |
171 buf = irc_format(irc, "vcn", "KICK", target, args[0]); |
| |
172 irc_send(irc, buf); |
| |
173 g_free(buf); |
| |
174 |
| |
175 return 0; |
| |
176 } |
| |
177 |
| |
178 int irc_cmd_mode(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
179 { |
| |
180 GaimConnection *gc; |
| |
181 char *buf; |
| |
182 |
| |
183 if (!args) |
| |
184 return 0; |
| |
185 |
| |
186 if (!strcmp(cmd, "mode")) { |
| |
187 if (!args[0] && (*target == '#' || *target == '&')) |
| |
188 buf = irc_format(irc, "vc", "MODE", target); |
| |
189 else if (args[0] && (*args[0] == '+' || *args[0] == '-')) |
| |
190 buf = irc_format(irc, "vcv", "MODE", target, args[0]); |
| |
191 else if (args[0]) |
| |
192 buf = irc_format(irc, "vv", "MODE", args[0]); |
| |
193 else |
| |
194 return; |
| |
195 } else if (!strcmp(cmd, "umode")) { |
| |
196 if (!args[0]) |
| |
197 return; |
| |
198 gc = gaim_account_get_connection(irc->account); |
| |
199 buf = irc_format(irc, "vnv", "MODE", gaim_connection_get_display_name(gc), args[0]); |
| |
200 } |
| |
201 irc_send(irc, buf); |
| |
202 g_free(buf); |
| |
203 |
| |
204 |
| |
205 return 0; |
| |
206 } |
| |
207 |
| |
208 int irc_cmd_names(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
209 { |
| |
210 char *buf; |
| |
211 |
| |
212 if (!args) |
| |
213 return 0; |
| |
214 |
| |
215 buf = irc_format(irc, "vc", "NAMES", args[0] ? args[0] : target); |
| |
216 irc_send(irc, buf); |
| |
217 g_free(buf); |
| |
218 |
| |
219 irc->nameconv = g_strdup(target); |
| |
220 |
| |
221 return 0; |
| |
222 } |
| |
223 |
| |
224 int irc_cmd_nick(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
225 { |
| |
226 char *buf; |
| |
227 |
| |
228 if (!args || !args[0]) |
| |
229 return 0; |
| |
230 |
| |
231 buf = irc_format(irc, "v:", "NICK", args[0]); |
| |
232 irc_send(irc, buf); |
| |
233 g_free(buf); |
| |
234 |
| |
235 return 0; |
| |
236 } |
| |
237 |
| |
238 int irc_cmd_op(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
239 { |
| |
240 char **nicks, **ops, *sign, *mode; |
| |
241 int i = 0, used = 0; |
| |
242 |
| |
243 if (!args || !args[0] || !*args[0]) |
| |
244 return 0; |
| |
245 |
| |
246 if (!strcmp(cmd, "op")) { |
| |
247 sign = "+"; |
| |
248 mode = "o"; |
| |
249 } else if (!strcmp(cmd, "deop")) { |
| |
250 sign = "-"; |
| |
251 mode = "o"; |
| |
252 } else if (!strcmp(cmd, "voice")) { |
| |
253 sign = "+"; |
| |
254 mode = "v"; |
| |
255 } else if (!strcmp(cmd, "devoice")) { |
| |
256 sign = "-"; |
| |
257 mode = "v"; |
| |
258 } else { |
| |
259 gaim_debug(GAIM_DEBUG_ERROR, "irc", "invalid 'op' command '%s'\n", cmd); |
| |
260 return 0; |
| |
261 } |
| |
262 |
| |
263 nicks = g_strsplit(args[0], " ", -1); |
| |
264 |
| |
265 for (i = 0; nicks[i]; i++) |
| |
266 /* nothing */; |
| |
267 ops = g_new0(char *, i * 2 + 1); |
| |
268 |
| |
269 for (i = 0; nicks[i]; i++) { |
| |
270 if (!*nicks[i]) |
| |
271 continue; |
| |
272 ops[used++] = mode; |
| |
273 ops[used++] = nicks[i]; |
| |
274 } |
| |
275 |
| |
276 irc_do_mode(irc, target, sign, ops); |
| |
277 g_free(ops); |
| |
278 |
| |
279 return; |
| |
280 } |
| |
281 |
| |
282 int irc_cmd_part(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
283 { |
| |
284 char *buf; |
| |
285 |
| |
286 if (!args) |
| |
287 return 0; |
| |
288 |
| |
289 if (args[1]) |
| |
290 buf = irc_format(irc, "vc:", "PART", args[0] ? args[0] : target, args[1]); |
| |
291 else |
| |
292 buf = irc_format(irc, "vc", "PART", args[0] ? args[0] : target); |
| |
293 irc_send(irc, buf); |
| |
294 g_free(buf); |
| |
295 |
| |
296 return 0; |
| |
297 } |
| |
298 |
| |
299 int irc_cmd_ping(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
300 { |
| |
301 char *stamp; |
| |
302 char *buf; |
| |
303 |
| |
304 if (args && args[0]) { |
| |
305 if (*args[0] == '#' || *args[0] == '&') |
| |
306 return 0; |
| |
307 stamp = g_strdup_printf("\001PING %lu\001", time(NULL)); |
| |
308 buf = irc_format(irc, "vn:", "PRIVMSG", args[0], stamp); |
| |
309 g_free(stamp); |
| |
310 } else { |
| |
311 stamp = g_strdup_printf("%s %d", target, time(NULL)); |
| |
312 buf = irc_format(irc, "v:", "PING", stamp); |
| |
313 g_free(stamp); |
| |
314 } |
| |
315 irc_send(irc, buf); |
| |
316 g_free(buf); |
| |
317 |
| |
318 return 0; |
| |
319 } |
| |
320 |
| |
321 int irc_cmd_privmsg(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
322 { |
| |
323 const char *cur, *end; |
| |
324 char *msg, *buf; |
| |
325 |
| |
326 if (!args || !args[0] || !args[1]) |
| |
327 return 0; |
| |
328 |
| |
329 cur = args[1]; |
| |
330 end = args[1]; |
| |
331 while (*end && *cur) { |
| |
332 end = strchr(cur, '\n'); |
| |
333 if (!end) |
| |
334 end = cur + strlen(cur); |
| |
335 msg = g_strndup(cur, end - cur); |
| |
336 buf = irc_format(irc, "vt:", "PRIVMSG", args[0], msg); |
| |
337 irc_send(irc, buf); |
| |
338 g_free(msg); |
| |
339 g_free(buf); |
| |
340 cur = end + 1; |
| |
341 } |
| |
342 |
| |
343 return 0; |
| |
344 } |
| |
345 |
| |
346 int irc_cmd_quit(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
347 { |
| |
348 char *buf; |
| |
349 |
| |
350 buf = irc_format(irc, "v:", "QUIT", (args && args[0]) ? args[0] : "Download Gaim: " WEBSITE); |
| |
351 irc_send(irc, buf); |
| |
352 g_free(buf); |
| |
353 |
| |
354 return 0; |
| |
355 } |
| |
356 |
| |
357 int irc_cmd_quote(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
358 { |
| |
359 char *buf; |
| |
360 |
| |
361 if (!args || !args[0]) |
| |
362 return 0; |
| |
363 |
| |
364 buf = irc_format(irc, "v", args[0]); |
| |
365 irc_send(irc, buf); |
| |
366 g_free(buf); |
| |
367 |
| |
368 return 0; |
| |
369 } |
| |
370 |
| |
371 int irc_cmd_query(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
372 { |
| |
373 GaimConversation *convo; |
| |
374 GaimConnection *gc; |
| |
375 |
| |
376 if (!args || !args[0]) |
| |
377 return 0; |
| |
378 |
| |
379 convo = gaim_conversation_new(GAIM_CONV_IM, irc->account, args[0]); |
| |
380 |
| |
381 if (args[1]) { |
| |
382 gc = gaim_account_get_connection(irc->account); |
| |
383 irc_cmd_privmsg(irc, cmd, target, args); |
| |
384 gaim_im_write(GAIM_IM(convo), gaim_connection_get_display_name(gc), |
| |
385 args[1], -1, WFLAG_SEND, time(NULL)); |
| |
386 } |
| |
387 |
| |
388 return 0; |
| |
389 } |
| |
390 |
| |
391 int irc_cmd_remove(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
392 { |
| |
393 char *buf; |
| |
394 |
| |
395 if (!args || !args[0]) |
| |
396 return 0; |
| |
397 |
| |
398 if (*target != '#' && *target != '&') /* not a channel, punt */ |
| |
399 return 0; |
| |
400 |
| |
401 if (args[1]) |
| |
402 buf = irc_format(irc, "vcn:", "REMOVE", target, args[0], args[1]); |
| |
403 else |
| |
404 buf = irc_format(irc, "vcn", "REMOVE", target, args[0]); |
| |
405 irc_send(irc, buf); |
| |
406 g_free(buf); |
| |
407 |
| |
408 return 0; |
| |
409 } |
| |
410 |
| |
411 int irc_cmd_topic(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
412 { |
| |
413 char *buf; |
| |
414 const char *topic; |
| |
415 GaimConversation *convo; |
| |
416 |
| |
417 if (!args) |
| |
418 return 0; |
| |
419 |
| |
420 convo = gaim_find_conversation_with_account(target, irc->account); |
| |
421 if (!convo || gaim_conversation_get_type(convo) != GAIM_CONV_CHAT) |
| |
422 return; |
| |
423 |
| |
424 if (!args[0]) { |
| |
425 topic = gaim_chat_get_topic (GAIM_CHAT(convo)); |
| |
426 |
| |
427 if (topic) |
| |
428 buf = g_strdup_printf("current topic is: %s", topic); |
| |
429 else |
| |
430 buf = g_strdup(_("No topic is set")); |
| |
431 gaim_chat_write(GAIM_CHAT(convo), target, buf, WFLAG_SYSTEM|WFLAG_NOLOG, time(NULL)); |
| |
432 g_free(buf); |
| |
433 |
| |
434 return 0; |
| |
435 } |
| |
436 |
| |
437 buf = irc_format(irc, "vt:", "TOPIC", target, args[0]); |
| |
438 irc_send(irc, buf); |
| |
439 g_free(buf); |
| |
440 |
| |
441 return 0; |
| |
442 } |
| |
443 |
| |
444 int irc_cmd_wallops(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
445 { |
| |
446 char *buf; |
| |
447 |
| |
448 if (!args || !args[0]) |
| |
449 return; |
| |
450 |
| |
451 if (!strcmp(cmd, "wallops")) |
| |
452 buf = irc_format(irc, "v:", "WALLOPS", args[0]); |
| |
453 else if (!strcmp(cmd, "operwall")) |
| |
454 buf = irc_format(irc, "v:", "OPERWALL", args[0]); |
| |
455 |
| |
456 irc_send(irc, buf); |
| |
457 g_free(buf); |
| |
458 |
| |
459 return 0; |
| |
460 } |
| |
461 |
| |
462 int irc_cmd_whois(struct irc_conn *irc, const char *cmd, const char *target, const char **args) |
| |
463 { |
| |
464 char *buf; |
| |
465 |
| |
466 if (!args || !args[0]) |
| |
467 return 0; |
| |
468 |
| |
469 buf = irc_format(irc, "vn", "WHOIS", args[0]); |
| |
470 irc_send(irc, buf); |
| |
471 g_free(buf); |
| |
472 irc->whois.nick = g_strdup(args[0]); |
| |
473 |
| |
474 return 0; |
| |
475 } |
| |
476 |
| |
477 static void irc_do_mode(struct irc_conn *irc, const char *target, const char *sign, char **ops) |
| |
478 { |
| |
479 char *buf, mode[5]; |
| |
480 int i = 0; |
| |
481 |
| |
482 if (!sign) |
| |
483 return; |
| |
484 |
| |
485 while (ops[i]) { |
| |
486 if (ops[i + 2] && ops[i + 4]) { |
| |
487 g_snprintf(mode, sizeof(mode), "%s%s%s%s", sign, |
| |
488 ops[i], ops[i + 2], ops[i + 4]); |
| |
489 buf = irc_format(irc, "vcvnnn", "MODE", target, mode, |
| |
490 ops[i + 1], ops[i + 3], ops[i + 5]); |
| |
491 i += 6; |
| |
492 } else if (ops[i + 2]) { |
| |
493 g_snprintf(mode, sizeof(mode), "%s%s%s", |
| |
494 sign, ops[i], ops[i + 2]); |
| |
495 buf = irc_format(irc, "vcvnn", "MODE", target, mode, |
| |
496 ops[i + 1], ops[i + 3]); |
| |
497 i += 4; |
| |
498 } else { |
| |
499 g_snprintf(mode, sizeof(mode), "%s%s", sign, ops[i]); |
| |
500 buf = irc_format(irc, "vcvn", "MODE", target, mode, ops[i + 1]); |
| |
501 i += 2; |
| |
502 } |
| |
503 irc_send(irc, buf); |
| |
504 g_free(buf); |
| |
505 } |
| |
506 } |