Mercurial > ~mikael > mcabber > hg
comparison mcabber/mcabber/commands.c @ 1668:41c26b7d2890
Install mcabber headers
* Change mcabber headers naming scheme
* Move 'src/' -> 'mcabber/'
* Add missing include <mcabber/config.h>'s
* Create and install clean config.h version in 'include/'
* Move "dirty" config.h version to 'mcabber/'
* Add $(top_srcdir) to compiler include path
* Update modules HOWTO
author | Myhailo Danylenko <isbear@ukrpost.net> |
---|---|
date | Mon, 18 Jan 2010 15:36:19 +0200 |
parents | mcabber/src/commands.c@64a7428afcb3 |
children | c73b31124fa6 |
comparison
equal
deleted
inserted
replaced
1667:8af0e0ad20ad | 1668:41c26b7d2890 |
---|---|
1 /* | |
2 * commands.c -- user commands handling | |
3 * | |
4 * Copyright (C) 2005-2009 Mikael Berthe <mikael@lilotux.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 (at | |
9 * your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * 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 | |
19 * USA | |
20 */ | |
21 | |
22 #include <string.h> | |
23 #include <stdlib.h> | |
24 #include <sys/types.h> | |
25 #include <sys/stat.h> | |
26 #include <unistd.h> | |
27 | |
28 #include "commands.h" | |
29 #include "help.h" | |
30 #include "roster.h" | |
31 #include "screen.h" | |
32 #include "compl.h" | |
33 #include "hooks.h" | |
34 #include "hbuf.h" | |
35 #include "utils.h" | |
36 #include "settings.h" | |
37 #include "events.h" | |
38 #include "otr.h" | |
39 #include "utf8.h" | |
40 #include "xmpp.h" | |
41 #include "main.h" | |
42 | |
43 #define IMSTATUS_AWAY "away" | |
44 #define IMSTATUS_ONLINE "online" | |
45 #define IMSTATUS_OFFLINE "offline" | |
46 #define IMSTATUS_FREE4CHAT "free" | |
47 #define IMSTATUS_INVISIBLE "invisible" | |
48 #define IMSTATUS_AVAILABLE "avail" | |
49 #define IMSTATUS_NOTAVAILABLE "notavail" | |
50 #define IMSTATUS_DONOTDISTURB "dnd" | |
51 | |
52 // Return value container for the following functions | |
53 static int retval_for_cmds; | |
54 | |
55 // Commands callbacks | |
56 static void do_roster(char *arg); | |
57 static void do_status(char *arg); | |
58 static void do_status_to(char *arg); | |
59 static void do_add(char *arg); | |
60 static void do_del(char *arg); | |
61 static void do_group(char *arg); | |
62 static void do_say(char *arg); | |
63 static void do_msay(char *arg); | |
64 static void do_say_to(char *arg); | |
65 static void do_buffer(char *arg); | |
66 static void do_clear(char *arg); | |
67 static void do_info(char *arg); | |
68 static void do_rename(char *arg); | |
69 static void do_move(char *arg); | |
70 static void do_set(char *arg); | |
71 static void do_alias(char *arg); | |
72 static void do_bind(char *arg); | |
73 static void do_connect(char *arg); | |
74 static void do_disconnect(char *arg); | |
75 static void do_rawxml(char *arg); | |
76 static void do_room(char *arg); | |
77 static void do_authorization(char *arg); | |
78 static void do_version(char *arg); | |
79 static void do_request(char *arg); | |
80 static void do_event(char *arg); | |
81 static void do_help(char *arg); | |
82 static void do_pgp(char *arg); | |
83 static void do_iline(char *arg); | |
84 static void do_screen_refresh(char *arg); | |
85 static void do_chat_disable(char *arg); | |
86 static void do_source(char *arg); | |
87 static void do_color(char *arg); | |
88 static void do_otr(char *arg); | |
89 static void do_otrpolicy(char *arg); | |
90 static void do_echo(char *arg); | |
91 | |
92 static void do_say_internal(char *arg, int parse_flags); | |
93 | |
94 // Global variable for the commands list | |
95 static GSList *Commands; | |
96 | |
97 #ifdef MODULES_ENABLE | |
98 #include <gmodule.h> | |
99 | |
100 static void do_load(char *arg); | |
101 static void do_unload(char *arg); | |
102 | |
103 typedef struct { | |
104 char *name; | |
105 GModule *module; | |
106 } loaded_module_t; | |
107 | |
108 GSList *loaded_modules = NULL; | |
109 | |
110 gpointer cmd_del(const char *name) | |
111 { | |
112 GSList *sl_cmd; | |
113 for (sl_cmd = Commands; sl_cmd; sl_cmd = sl_cmd->next) { | |
114 cmd *command = (cmd *) sl_cmd->data; | |
115 if (!strcmp (command->name, name)) { | |
116 gpointer userdata = command->userdata; | |
117 Commands = g_slist_delete_link(Commands, sl_cmd); | |
118 compl_del_category_word(COMPL_CMD, command->name); | |
119 g_free(command); | |
120 return userdata; | |
121 } | |
122 } | |
123 return NULL; | |
124 } | |
125 | |
126 // cmd_add() | |
127 // Adds a command to the commands list and to the CMD completion list | |
128 void cmd_add(const char *name, const char *help, guint flags_row1, | |
129 guint flags_row2, void (*f)(char*), gpointer userdata) | |
130 #define cmd_add(A, B, C, D, E) cmd_add (A, B, C, D, E, NULL); | |
131 #else | |
132 static void cmd_add(const char *name, const char *help, | |
133 guint flags_row1, guint flags_row2, void (*f)(char*)) | |
134 #endif | |
135 { | |
136 cmd *n_cmd = g_new0(cmd, 1); | |
137 strncpy(n_cmd->name, name, 32-1); | |
138 n_cmd->help = help; | |
139 n_cmd->completion_flags[0] = flags_row1; | |
140 n_cmd->completion_flags[1] = flags_row2; | |
141 n_cmd->func = f; | |
142 #ifdef MODULES_ENABLE | |
143 n_cmd->userdata = userdata; | |
144 #endif | |
145 Commands = g_slist_prepend(Commands, n_cmd); | |
146 // Add to completion CMD category | |
147 compl_add_category_word(COMPL_CMD, name); | |
148 } | |
149 | |
150 // cmd_init() | |
151 // Commands table initialization | |
152 // !!! | |
153 // After changing commands names and it arguments names here, you must change | |
154 // ones in init_bindings()! | |
155 // | |
156 void cmd_init(void) | |
157 { | |
158 cmd_add("add", "Add a jabber user", COMPL_JID, 0, &do_add); | |
159 cmd_add("alias", "Add an alias", 0, 0, &do_alias); | |
160 cmd_add("authorization", "Manage subscription authorizations", | |
161 COMPL_AUTH, COMPL_JID, &do_authorization); | |
162 cmd_add("bind", "Add an key binding", 0, 0, &do_bind); | |
163 cmd_add("buffer", "Manipulate current buddy's buffer (chat window)", | |
164 COMPL_BUFFER, 0, &do_buffer); | |
165 cmd_add("chat_disable", "Disable chat mode", 0, 0, &do_chat_disable); | |
166 cmd_add("clear", "Clear the dialog window", 0, 0, &do_clear); | |
167 cmd_add("color", "Set coloring options", COMPL_COLOR, 0, &do_color); | |
168 cmd_add("connect", "Connect to the server", 0, 0, &do_connect); | |
169 cmd_add("del", "Delete the current buddy", 0, 0, &do_del); | |
170 cmd_add("disconnect", "Disconnect from server", 0, 0, &do_disconnect); | |
171 cmd_add("echo", "Display a string in the log window", 0, 0, &do_echo); | |
172 cmd_add("event", "Process an event", COMPL_EVENTSID, COMPL_EVENTS, &do_event); | |
173 cmd_add("group", "Change group display settings", | |
174 COMPL_GROUP, COMPL_GROUPNAME, &do_group); | |
175 cmd_add("help", "Display some help", COMPL_CMD, 0, &do_help); | |
176 cmd_add("iline", "Manipulate input buffer", 0, 0, &do_iline); | |
177 cmd_add("info", "Show basic info on current buddy", 0, 0, &do_info); | |
178 cmd_add("move", "Move the current buddy to another group", COMPL_GROUPNAME, | |
179 0, &do_move); | |
180 cmd_add("msay", "Send a multi-lines message to the selected buddy", | |
181 COMPL_MULTILINE, 0, &do_msay); | |
182 cmd_add("otr", "Manage OTR settings", COMPL_OTR, COMPL_JID, &do_otr); | |
183 cmd_add("otrpolicy", "Manage OTR policies", COMPL_JID, COMPL_OTRPOLICY, | |
184 &do_otrpolicy); | |
185 cmd_add("pgp", "Manage PGP settings", COMPL_PGP, COMPL_JID, &do_pgp); | |
186 cmd_add("quit", "Exit the software", 0, 0, NULL); | |
187 cmd_add("rawxml", "Send a raw XML string", 0, 0, &do_rawxml); | |
188 cmd_add("rename", "Rename the current buddy", 0, 0, &do_rename); | |
189 cmd_add("request", "Send a Jabber IQ request", COMPL_REQUEST, COMPL_JID, | |
190 &do_request); | |
191 cmd_add("room", "MUC actions command", COMPL_ROOM, 0, &do_room); | |
192 cmd_add("roster", "Manipulate the roster/buddylist", COMPL_ROSTER, 0, | |
193 &do_roster); | |
194 cmd_add("say", "Say something to the selected buddy", 0, 0, &do_say); | |
195 cmd_add("say_to", "Say something to a specific buddy", COMPL_JID, 0, | |
196 &do_say_to); | |
197 cmd_add("screen_refresh", "Redraw mcabber screen", 0, 0, &do_screen_refresh); | |
198 //cmd_add("search"); | |
199 cmd_add("set", "Set/query an option value", 0, 0, &do_set); | |
200 cmd_add("source", "Read a configuration file", 0, 0, &do_source); | |
201 cmd_add("status", "Show or set your status", COMPL_STATUS, 0, &do_status); | |
202 cmd_add("status_to", "Show or set your status for one recipient", | |
203 COMPL_JID, COMPL_STATUS, &do_status_to); | |
204 cmd_add("version", "Show mcabber version", 0, 0, &do_version); | |
205 #ifdef MODULES_ENABLE | |
206 cmd_add("load", "Load module", 0, 0, &do_load); | |
207 cmd_add("unload", "Unload module", 0, 0, &do_unload); | |
208 #endif | |
209 | |
210 // Status category | |
211 compl_add_category_word(COMPL_STATUS, "online"); | |
212 compl_add_category_word(COMPL_STATUS, "avail"); | |
213 compl_add_category_word(COMPL_STATUS, "invisible"); | |
214 compl_add_category_word(COMPL_STATUS, "free"); | |
215 compl_add_category_word(COMPL_STATUS, "dnd"); | |
216 compl_add_category_word(COMPL_STATUS, "notavail"); | |
217 compl_add_category_word(COMPL_STATUS, "away"); | |
218 compl_add_category_word(COMPL_STATUS, "offline"); | |
219 compl_add_category_word(COMPL_STATUS, "message"); | |
220 | |
221 // Roster category | |
222 compl_add_category_word(COMPL_ROSTER, "bottom"); | |
223 compl_add_category_word(COMPL_ROSTER, "top"); | |
224 compl_add_category_word(COMPL_ROSTER, "up"); | |
225 compl_add_category_word(COMPL_ROSTER, "down"); | |
226 compl_add_category_word(COMPL_ROSTER, "group_prev"); | |
227 compl_add_category_word(COMPL_ROSTER, "group_next"); | |
228 compl_add_category_word(COMPL_ROSTER, "hide"); | |
229 compl_add_category_word(COMPL_ROSTER, "show"); | |
230 compl_add_category_word(COMPL_ROSTER, "toggle"); | |
231 compl_add_category_word(COMPL_ROSTER, "display"); | |
232 compl_add_category_word(COMPL_ROSTER, "hide_offline"); | |
233 compl_add_category_word(COMPL_ROSTER, "show_offline"); | |
234 compl_add_category_word(COMPL_ROSTER, "toggle_offline"); | |
235 compl_add_category_word(COMPL_ROSTER, "item_lock"); | |
236 compl_add_category_word(COMPL_ROSTER, "item_unlock"); | |
237 compl_add_category_word(COMPL_ROSTER, "item_toggle_lock"); | |
238 compl_add_category_word(COMPL_ROSTER, "alternate"); | |
239 compl_add_category_word(COMPL_ROSTER, "search"); | |
240 compl_add_category_word(COMPL_ROSTER, "unread_first"); | |
241 compl_add_category_word(COMPL_ROSTER, "unread_next"); | |
242 compl_add_category_word(COMPL_ROSTER, "note"); | |
243 | |
244 // Buffer category | |
245 compl_add_category_word(COMPL_BUFFER, "clear"); | |
246 compl_add_category_word(COMPL_BUFFER, "bottom"); | |
247 compl_add_category_word(COMPL_BUFFER, "top"); | |
248 compl_add_category_word(COMPL_BUFFER, "up"); | |
249 compl_add_category_word(COMPL_BUFFER, "down"); | |
250 compl_add_category_word(COMPL_BUFFER, "search_backward"); | |
251 compl_add_category_word(COMPL_BUFFER, "search_forward"); | |
252 compl_add_category_word(COMPL_BUFFER, "date"); | |
253 compl_add_category_word(COMPL_BUFFER, "%"); | |
254 compl_add_category_word(COMPL_BUFFER, "purge"); | |
255 compl_add_category_word(COMPL_BUFFER, "close"); | |
256 compl_add_category_word(COMPL_BUFFER, "close_all"); | |
257 compl_add_category_word(COMPL_BUFFER, "scroll_lock"); | |
258 compl_add_category_word(COMPL_BUFFER, "scroll_unlock"); | |
259 compl_add_category_word(COMPL_BUFFER, "scroll_toggle"); | |
260 compl_add_category_word(COMPL_BUFFER, "list"); | |
261 compl_add_category_word(COMPL_BUFFER, "save"); | |
262 | |
263 // Group category | |
264 compl_add_category_word(COMPL_GROUP, "fold"); | |
265 compl_add_category_word(COMPL_GROUP, "unfold"); | |
266 compl_add_category_word(COMPL_GROUP, "toggle"); | |
267 | |
268 // Multi-line (msay) category | |
269 compl_add_category_word(COMPL_MULTILINE, "abort"); | |
270 compl_add_category_word(COMPL_MULTILINE, "begin"); | |
271 compl_add_category_word(COMPL_MULTILINE, "send"); | |
272 compl_add_category_word(COMPL_MULTILINE, "send_to"); | |
273 compl_add_category_word(COMPL_MULTILINE, "toggle"); | |
274 compl_add_category_word(COMPL_MULTILINE, "toggle_verbatim"); | |
275 compl_add_category_word(COMPL_MULTILINE, "verbatim"); | |
276 | |
277 // Room category | |
278 compl_add_category_word(COMPL_ROOM, "affil"); | |
279 compl_add_category_word(COMPL_ROOM, "ban"); | |
280 compl_add_category_word(COMPL_ROOM, "bookmark"); | |
281 compl_add_category_word(COMPL_ROOM, "destroy"); | |
282 compl_add_category_word(COMPL_ROOM, "invite"); | |
283 compl_add_category_word(COMPL_ROOM, "join"); | |
284 compl_add_category_word(COMPL_ROOM, "kick"); | |
285 compl_add_category_word(COMPL_ROOM, "leave"); | |
286 compl_add_category_word(COMPL_ROOM, "names"); | |
287 compl_add_category_word(COMPL_ROOM, "nick"); | |
288 compl_add_category_word(COMPL_ROOM, "privmsg"); | |
289 compl_add_category_word(COMPL_ROOM, "remove"); | |
290 compl_add_category_word(COMPL_ROOM, "role"); | |
291 compl_add_category_word(COMPL_ROOM, "setopt"); | |
292 compl_add_category_word(COMPL_ROOM, "topic"); | |
293 compl_add_category_word(COMPL_ROOM, "unban"); | |
294 compl_add_category_word(COMPL_ROOM, "unlock"); | |
295 compl_add_category_word(COMPL_ROOM, "whois"); | |
296 | |
297 // Authorization category | |
298 compl_add_category_word(COMPL_AUTH, "allow"); | |
299 compl_add_category_word(COMPL_AUTH, "cancel"); | |
300 compl_add_category_word(COMPL_AUTH, "request"); | |
301 compl_add_category_word(COMPL_AUTH, "request_unsubscribe"); | |
302 | |
303 // Request (query) category | |
304 compl_add_category_word(COMPL_REQUEST, "last"); | |
305 compl_add_category_word(COMPL_REQUEST, "time"); | |
306 compl_add_category_word(COMPL_REQUEST, "vcard"); | |
307 compl_add_category_word(COMPL_REQUEST, "version"); | |
308 | |
309 // Events category | |
310 compl_add_category_word(COMPL_EVENTS, "accept"); | |
311 compl_add_category_word(COMPL_EVENTS, "ignore"); | |
312 compl_add_category_word(COMPL_EVENTS, "reject"); | |
313 | |
314 // PGP category | |
315 compl_add_category_word(COMPL_PGP, "disable"); | |
316 compl_add_category_word(COMPL_PGP, "enable"); | |
317 compl_add_category_word(COMPL_PGP, "force"); | |
318 compl_add_category_word(COMPL_PGP, "info"); | |
319 compl_add_category_word(COMPL_PGP, "setkey"); | |
320 | |
321 // OTR category | |
322 compl_add_category_word(COMPL_OTR, "start"); | |
323 compl_add_category_word(COMPL_OTR, "stop"); | |
324 compl_add_category_word(COMPL_OTR, "fingerprint"); | |
325 compl_add_category_word(COMPL_OTR, "smpq"); | |
326 compl_add_category_word(COMPL_OTR, "smpr"); | |
327 compl_add_category_word(COMPL_OTR, "smpa"); | |
328 compl_add_category_word(COMPL_OTR, "info"); | |
329 compl_add_category_word(COMPL_OTR, "key"); | |
330 | |
331 // OTR Policy category | |
332 compl_add_category_word(COMPL_OTRPOLICY, "plain"); | |
333 compl_add_category_word(COMPL_OTRPOLICY, "manual"); | |
334 compl_add_category_word(COMPL_OTRPOLICY, "opportunistic"); | |
335 compl_add_category_word(COMPL_OTRPOLICY, "always"); | |
336 | |
337 // Color category | |
338 compl_add_category_word(COMPL_COLOR, "roster"); | |
339 compl_add_category_word(COMPL_COLOR, "muc"); | |
340 compl_add_category_word(COMPL_COLOR, "mucnick"); | |
341 } | |
342 | |
343 #ifdef MODULES_ENABLE | |
344 void cmd_deinit () | |
345 { | |
346 GSList *el = loaded_modules; | |
347 while (el) { | |
348 loaded_module_t *module = el->data; | |
349 if (!g_module_close ((GModule *) module->module)) | |
350 scr_LogPrint (LPRINT_LOGNORM, "* Module unloading failed: %s", | |
351 g_module_error ()); | |
352 g_free (module->name); | |
353 g_free (module); | |
354 el = g_slist_next (el); | |
355 } | |
356 g_slist_free (loaded_modules); | |
357 } | |
358 #endif | |
359 | |
360 // expandalias(line) | |
361 // If there is one, expand the alias in line and returns a new allocated line | |
362 // If no alias is found, returns line | |
363 // Note: if the returned pointer is different from line, the caller should | |
364 // g_free() the pointer after use | |
365 char *expandalias(const char *line) | |
366 { | |
367 const char *p1, *p2; | |
368 char *word; | |
369 const gchar *value; | |
370 char *newline = (char*)line; | |
371 | |
372 // Ignore leading COMMAND_CHAR | |
373 for (p1 = line ; *p1 == COMMAND_CHAR ; p1++) | |
374 ; | |
375 // Locate the end of the word | |
376 for (p2 = p1 ; *p2 && (*p2 != ' ') ; p2++) | |
377 ; | |
378 // Extract the word and look for an alias in the list | |
379 word = g_strndup(p1, p2-p1); | |
380 value = settings_get(SETTINGS_TYPE_ALIAS, (const char*)word); | |
381 g_free(word); | |
382 | |
383 if (value) | |
384 newline = g_strdup_printf("%c%s%s", COMMAND_CHAR, value, p2); | |
385 | |
386 return newline; | |
387 } | |
388 | |
389 // cmd_get | |
390 // Finds command in the command list structure. | |
391 // Returns a pointer to the cmd entry, or NULL if command not found. | |
392 cmd *cmd_get(const char *command) | |
393 { | |
394 const char *p1, *p2; | |
395 char *com; | |
396 GSList *sl_com; | |
397 | |
398 // Ignore leading COMMAND_CHAR | |
399 for (p1 = command ; *p1 == COMMAND_CHAR ; p1++) | |
400 ; | |
401 // Locate the end of the command | |
402 for (p2 = p1 ; *p2 && (*p2 != ' ') ; p2++) | |
403 ; | |
404 // Copy the clean command | |
405 com = g_strndup(p1, p2-p1); | |
406 | |
407 // Look for command in the list | |
408 for (sl_com=Commands; sl_com; sl_com = g_slist_next(sl_com)) { | |
409 if (!strcasecmp(com, ((cmd*)sl_com->data)->name)) | |
410 break; | |
411 } | |
412 g_free(com); | |
413 | |
414 if (sl_com) // Command has been found. | |
415 return (cmd*)sl_com->data; | |
416 return NULL; | |
417 } | |
418 | |
419 // process_command(line, iscmd) | |
420 // Process a command line. | |
421 // If iscmd is TRUE, process the command even if verbatim mmode is set; | |
422 // it is intended to be used for key bindings. | |
423 // Return 255 if this is the /quit command, and 0 for the other commands. | |
424 int process_command(const char *line, guint iscmd) | |
425 { | |
426 char *p; | |
427 char *xpline; | |
428 cmd *curcmd; | |
429 | |
430 if (!line) | |
431 return 0; | |
432 | |
433 // We do alias expansion here | |
434 if (iscmd || scr_get_multimode() != 2) | |
435 xpline = expandalias(line); | |
436 else | |
437 xpline = (char*)line; // No expansion in verbatim multi-line mode | |
438 | |
439 // We want to use a copy | |
440 if (xpline == line) | |
441 xpline = g_strdup(line); | |
442 | |
443 // Remove trailing spaces: | |
444 for (p=xpline ; *p ; p++) | |
445 ; | |
446 for (p-- ; p>xpline && (*p == ' ') ; p--) | |
447 *p = 0; | |
448 | |
449 // Command "quit"? | |
450 if ((iscmd || scr_get_multimode() != 2) | |
451 && (!strncasecmp(xpline, mkcmdstr("quit"), strlen(mkcmdstr("quit"))))) { | |
452 if (!xpline[5] || xpline[5] == ' ') { | |
453 g_free(xpline); | |
454 return 255; | |
455 } | |
456 } else if (iscmd && !strncasecmp(xpline, "quit", 4) && | |
457 (!xpline[4] || xpline[4] == ' ')) { | |
458 // If iscmd is true we can have the command without the command prefix | |
459 // character (usually '/'). | |
460 g_free(xpline); | |
461 return 255; | |
462 } | |
463 | |
464 // If verbatim multi-line mode, we check if another /msay command is typed | |
465 if (!iscmd && scr_get_multimode() == 2 | |
466 && (strncasecmp(xpline, mkcmdstr("msay "), strlen(mkcmdstr("msay "))))) { | |
467 // It isn't an /msay command | |
468 scr_append_multiline(xpline); | |
469 g_free(xpline); | |
470 return 0; | |
471 } | |
472 | |
473 // Commands handling | |
474 curcmd = cmd_get(xpline); | |
475 | |
476 if (!curcmd) { | |
477 scr_LogPrint(LPRINT_NORMAL, "Unrecognized command. " | |
478 "Please see the manual for a list of known commands."); | |
479 g_free(xpline); | |
480 return 0; | |
481 } | |
482 if (!curcmd->func) { | |
483 scr_LogPrint(LPRINT_NORMAL, | |
484 "This functionality is not yet implemented, sorry."); | |
485 g_free(xpline); | |
486 return 0; | |
487 } | |
488 // Lets go to the command parameters | |
489 for (p = xpline+1; *p && (*p != ' ') ; p++) | |
490 ; | |
491 // Skip spaces | |
492 while (*p && (*p == ' ')) | |
493 p++; | |
494 // Call command-specific function | |
495 retval_for_cmds = 0; | |
496 #ifdef MODULES_ENABLE | |
497 if (curcmd->userdata) | |
498 (*(void (*)(char *p, gpointer u))curcmd->func)(p, curcmd->userdata); | |
499 else | |
500 (*curcmd->func)(p); | |
501 #else | |
502 (*curcmd->func)(p); | |
503 #endif | |
504 g_free(xpline); | |
505 return retval_for_cmds; | |
506 } | |
507 | |
508 // process_line(line) | |
509 // Process a command/message line. | |
510 // If this isn't a command, this is a message and it is sent to the | |
511 // currently selected buddy. | |
512 // Return 255 if the line is the /quit command, or 0. | |
513 int process_line(const char *line) | |
514 { | |
515 if (!*line) { // User only pressed enter | |
516 if (scr_get_multimode()) { | |
517 scr_append_multiline(""); | |
518 return 0; | |
519 } | |
520 if (current_buddy) { | |
521 if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP) | |
522 do_group("toggle"); | |
523 else { | |
524 // Enter chat mode | |
525 scr_set_chatmode(TRUE); | |
526 scr_ShowBuddyWindow(); | |
527 } | |
528 } | |
529 return 0; | |
530 } | |
531 | |
532 if (*line != COMMAND_CHAR) { | |
533 // This isn't a command | |
534 if (scr_get_multimode()) | |
535 scr_append_multiline(line); | |
536 else | |
537 do_say_internal((char*)line, 0); | |
538 return 0; | |
539 } | |
540 | |
541 /* It is _probably_ a command -- except for verbatim multi-line mode */ | |
542 return process_command(line, FALSE); | |
543 } | |
544 | |
545 // Helper routine for buffer item_{lock,unlock,toggle_lock} | |
546 // "lock" values: 1=lock 0=unlock -1=invert | |
547 static void roster_buddylock(char *bjid, int lock) | |
548 { | |
549 gpointer bud = NULL; | |
550 bool may_need_refresh = FALSE; | |
551 | |
552 // Allow special jid "" or "." (current buddy) | |
553 if (bjid && (!*bjid || !strcmp(bjid, "."))) | |
554 bjid = NULL; | |
555 | |
556 if (bjid) { | |
557 // The JID has been specified. Quick check... | |
558 if (check_jid_syntax(bjid)) { | |
559 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
560 "<%s> is not a valid Jabber ID.", bjid); | |
561 } else { | |
562 // Find the buddy | |
563 GSList *roster_elt; | |
564 roster_elt = roster_find(bjid, jidsearch, | |
565 ROSTER_TYPE_USER|ROSTER_TYPE_ROOM); | |
566 if (roster_elt) | |
567 bud = roster_elt->data; | |
568 else | |
569 scr_LogPrint(LPRINT_NORMAL, "This jid isn't in the roster."); | |
570 may_need_refresh = TRUE; | |
571 } | |
572 } else { | |
573 // Use the current buddy | |
574 if (current_buddy) | |
575 bud = BUDDATA(current_buddy); | |
576 } | |
577 | |
578 // Update the ROSTER_FLAG_USRLOCK flag | |
579 if (bud) { | |
580 if (lock == -1) | |
581 lock = !(buddy_getflags(bud) & ROSTER_FLAG_USRLOCK); | |
582 buddy_setflags(bud, ROSTER_FLAG_USRLOCK, lock); | |
583 if (may_need_refresh) { | |
584 buddylist_build(); | |
585 update_roster = TRUE; | |
586 } | |
587 } | |
588 } | |
589 | |
590 // display_and_free_note(note, winId) | |
591 // Display the note information in the winId buffer, and free note | |
592 // (winId is a bare jid or NULL for the status window, in which case we | |
593 // display the note jid too) | |
594 static void display_and_free_note(struct annotation *note, const char *winId) | |
595 { | |
596 gchar tbuf[128]; | |
597 GString *sbuf; | |
598 guint msg_flag = HBB_PREFIX_INFO; | |
599 /* We use the flag prefix_info for the first line, and prefix_cont | |
600 for the other lines, for better readability */ | |
601 | |
602 if (!note) | |
603 return; | |
604 | |
605 sbuf = g_string_new(""); | |
606 | |
607 if (!winId) { | |
608 // We're writing to the status window, so let's show the jid too. | |
609 g_string_printf(sbuf, "Annotation on <%s>", note->jid); | |
610 scr_WriteIncomingMessage(winId, sbuf->str, 0, msg_flag, 0); | |
611 msg_flag = HBB_PREFIX_INFO | HBB_PREFIX_CONT; | |
612 } | |
613 | |
614 // If we have the creation date, display it | |
615 if (note->cdate) { | |
616 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", | |
617 localtime(¬e->cdate)); | |
618 g_string_printf(sbuf, "Note created %s", tbuf); | |
619 scr_WriteIncomingMessage(winId, sbuf->str, 0, msg_flag, 0); | |
620 msg_flag = HBB_PREFIX_INFO | HBB_PREFIX_CONT; | |
621 } | |
622 // If we have the modification date, display it | |
623 // unless it's the same as the creation date | |
624 if (note->mdate && note->mdate != note->cdate) { | |
625 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", | |
626 localtime(¬e->mdate)); | |
627 g_string_printf(sbuf, "Note modified %s", tbuf); | |
628 scr_WriteIncomingMessage(winId, sbuf->str, 0, msg_flag, 0); | |
629 msg_flag = HBB_PREFIX_INFO | HBB_PREFIX_CONT; | |
630 } | |
631 // Note text | |
632 g_string_printf(sbuf, "Note: %s", note->text); | |
633 scr_WriteIncomingMessage(winId, sbuf->str, 0, msg_flag, 0); | |
634 | |
635 g_string_free(sbuf, TRUE); | |
636 g_free(note->text); | |
637 g_free(note->jid); | |
638 g_free(note); | |
639 } | |
640 | |
641 static void display_all_annotations(void) | |
642 { | |
643 GSList *notes; | |
644 notes = xmpp_get_all_storage_rosternotes(); | |
645 | |
646 if (!notes) | |
647 return; | |
648 | |
649 // Call display_and_free_note() for each note, | |
650 // with winId = NULL (special window) | |
651 g_slist_foreach(notes, (GFunc)&display_and_free_note, NULL); | |
652 scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE); | |
653 update_roster = TRUE; | |
654 g_slist_free(notes); | |
655 } | |
656 | |
657 static void roster_note(char *arg) | |
658 { | |
659 const char *bjid; | |
660 guint type; | |
661 | |
662 if (!current_buddy) | |
663 return; | |
664 | |
665 bjid = buddy_getjid(BUDDATA(current_buddy)); | |
666 type = buddy_gettype(BUDDATA(current_buddy)); | |
667 | |
668 if (!bjid && type == ROSTER_TYPE_SPECIAL && !arg) { | |
669 // We're in the status window (the only special buffer currently) | |
670 // Let's display all server notes | |
671 display_all_annotations(); | |
672 return; | |
673 } | |
674 | |
675 if (!bjid || (type != ROSTER_TYPE_USER && | |
676 type != ROSTER_TYPE_ROOM && | |
677 type != ROSTER_TYPE_AGENT)) { | |
678 scr_LogPrint(LPRINT_NORMAL, "This item can't have a note."); | |
679 return; | |
680 } | |
681 | |
682 if (arg && *arg) { // Set a note | |
683 gchar *msg, *notetxt; | |
684 msg = to_utf8(arg); | |
685 if (!strcmp(msg, "-")) | |
686 notetxt = NULL; // delete note | |
687 else | |
688 notetxt = msg; | |
689 xmpp_set_storage_rosternotes(bjid, notetxt); | |
690 g_free(msg); | |
691 } else { // Display a note | |
692 struct annotation *note = xmpp_get_storage_rosternotes(bjid, FALSE); | |
693 if (note) { | |
694 display_and_free_note(note, bjid); | |
695 } else { | |
696 scr_WriteIncomingMessage(bjid, "This item doesn't have a note.", 0, | |
697 HBB_PREFIX_INFO, 0); | |
698 } | |
699 } | |
700 } | |
701 | |
702 // roster_updown(updown, nitems) | |
703 // updown: -1=up, +1=down | |
704 inline static void roster_updown(int updown, char *nitems) | |
705 { | |
706 int nbitems; | |
707 | |
708 if (!nitems || !*nitems) | |
709 nbitems = 1; | |
710 else | |
711 nbitems = strtol(nitems, NULL, 10); | |
712 | |
713 if (nbitems > 0) | |
714 scr_RosterUpDown(updown, nbitems); | |
715 } | |
716 | |
717 /* Commands callback functions */ | |
718 /* All these do_*() functions will be called with a "arg" parameter */ | |
719 /* (with arg not null) */ | |
720 | |
721 static void do_roster(char *arg) | |
722 { | |
723 char **paramlst; | |
724 char *subcmd; | |
725 | |
726 paramlst = split_arg(arg, 2, 1); // subcmd, arg | |
727 subcmd = *paramlst; | |
728 arg = *(paramlst+1); | |
729 | |
730 if (!subcmd || !*subcmd) { | |
731 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
732 free_arg_lst(paramlst); | |
733 return; | |
734 } | |
735 | |
736 if (!strcasecmp(subcmd, "top")) { | |
737 scr_RosterTop(); | |
738 update_roster = TRUE; | |
739 } else if (!strcasecmp(subcmd, "bottom")) { | |
740 scr_RosterBottom(); | |
741 update_roster = TRUE; | |
742 } else if (!strcasecmp(subcmd, "hide")) { | |
743 scr_RosterVisibility(0); | |
744 } else if (!strcasecmp(subcmd, "show")) { | |
745 scr_RosterVisibility(1); | |
746 } else if (!strcasecmp(subcmd, "toggle")) { | |
747 scr_RosterVisibility(-1); | |
748 } else if (!strcasecmp(subcmd, "hide_offline")) { | |
749 buddylist_set_hide_offline_buddies(TRUE); | |
750 if (current_buddy) | |
751 buddylist_build(); | |
752 update_roster = TRUE; | |
753 } else if (!strcasecmp(subcmd, "show_offline")) { | |
754 buddylist_set_hide_offline_buddies(FALSE); | |
755 buddylist_build(); | |
756 update_roster = TRUE; | |
757 } else if (!strcasecmp(subcmd, "toggle_offline")) { | |
758 buddylist_set_hide_offline_buddies(-1); | |
759 buddylist_build(); | |
760 update_roster = TRUE; | |
761 } else if (!strcasecmp(subcmd, "display")) { | |
762 scr_RosterDisplay(arg); | |
763 } else if (!strcasecmp(subcmd, "item_lock")) { | |
764 roster_buddylock(arg, 1); | |
765 } else if (!strcasecmp(subcmd, "item_unlock")) { | |
766 roster_buddylock(arg, 0); | |
767 } else if (!strcasecmp(subcmd, "item_toggle_lock")) { | |
768 roster_buddylock(arg, -1); | |
769 } else if (!strcasecmp(subcmd, "unread_first")) { | |
770 scr_RosterUnreadMessage(0); | |
771 } else if (!strcasecmp(subcmd, "unread_next")) { | |
772 scr_RosterUnreadMessage(1); | |
773 } else if (!strcasecmp(subcmd, "alternate")) { | |
774 scr_RosterJumpAlternate(); | |
775 } else if (!strncasecmp(subcmd, "search", 6)) { | |
776 strip_arg_special_chars(arg); | |
777 if (!arg || !*arg) { | |
778 scr_LogPrint(LPRINT_NORMAL, "What name or JID are you looking for?"); | |
779 free_arg_lst(paramlst); | |
780 return; | |
781 } | |
782 scr_RosterSearch(arg); | |
783 update_roster = TRUE; | |
784 } else if (!strcasecmp(subcmd, "up")) { | |
785 roster_updown(-1, arg); | |
786 } else if (!strcasecmp(subcmd, "down")) { | |
787 roster_updown(1, arg); | |
788 } else if (!strcasecmp(subcmd, "group_prev")) { | |
789 scr_RosterPrevGroup(); | |
790 } else if (!strcasecmp(subcmd, "group_next")) { | |
791 scr_RosterNextGroup(); | |
792 } else if (!strcasecmp(subcmd, "note")) { | |
793 roster_note(arg); | |
794 } else | |
795 scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); | |
796 free_arg_lst(paramlst); | |
797 } | |
798 | |
799 void do_color(char *arg) | |
800 { | |
801 char **paramlst; | |
802 char *subcmd; | |
803 | |
804 paramlst = split_arg(arg, 2, 1); // subcmd, arg | |
805 subcmd = *paramlst; | |
806 arg = *(paramlst+1); | |
807 | |
808 if (!subcmd || !*subcmd) { | |
809 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
810 free_arg_lst(paramlst); | |
811 return; | |
812 } | |
813 | |
814 if (!strcasecmp(subcmd, "roster")) { | |
815 char *status, *wildcard, *color; | |
816 char **arglist = split_arg(arg, 3, 0); | |
817 | |
818 status = *arglist; | |
819 wildcard = to_utf8(arglist[1]); | |
820 color = arglist[2]; | |
821 | |
822 if (status && !strcmp(status, "clear")) { // Not a color command, clear all | |
823 scr_RosterClearColor(); | |
824 update_roster = TRUE; | |
825 } else { | |
826 if (!status || !*status || !wildcard || !*wildcard || !color || !*color) { | |
827 scr_LogPrint(LPRINT_NORMAL, "Missing argument"); | |
828 } else { | |
829 update_roster = scr_RosterColor(status, wildcard, color) | |
830 || update_roster; | |
831 } | |
832 } | |
833 free_arg_lst(arglist); | |
834 g_free(wildcard); | |
835 } else if (!strcasecmp(subcmd, "muc")) { | |
836 char **arglist = split_arg(arg, 2, 0); | |
837 char *free_muc = to_utf8(*arglist); | |
838 const char *muc = free_muc, *mode = arglist[1]; | |
839 if (!muc || !*muc) | |
840 scr_LogPrint(LPRINT_NORMAL, "What MUC?"); | |
841 else { | |
842 if (!strcmp(muc, ".")) | |
843 if (!(muc = CURRENT_JID)) | |
844 scr_LogPrint(LPRINT_NORMAL, "No JID selected"); | |
845 if (muc) { | |
846 if (check_jid_syntax(muc) && strcmp(muc, "*")) | |
847 scr_LogPrint(LPRINT_NORMAL, "Not a JID"); | |
848 else { | |
849 if (!mode || !*mode || !strcasecmp(mode, "on")) | |
850 scr_MucColor(muc, MC_ALL); | |
851 else if (!strcasecmp(mode, "preset")) | |
852 scr_MucColor(muc, MC_PRESET); | |
853 else if (!strcasecmp(mode, "off")) | |
854 scr_MucColor(muc, MC_OFF); | |
855 else if (!strcmp(mode, "-")) | |
856 scr_MucColor(muc, MC_REMOVE); | |
857 else | |
858 scr_LogPrint(LPRINT_NORMAL, "Unknown coloring mode"); | |
859 } | |
860 } | |
861 } | |
862 free_arg_lst(arglist); | |
863 g_free(free_muc); | |
864 } else if (!strcasecmp(subcmd, "mucnick")) { | |
865 char **arglist = split_arg(arg, 2, 0); | |
866 const char *nick = *arglist, *color = arglist[1]; | |
867 if (!nick || !*nick || !color || !*color) | |
868 scr_LogPrint(LPRINT_NORMAL, "Missing argument"); | |
869 else | |
870 scr_MucNickColor(nick, color); | |
871 free_arg_lst(arglist); | |
872 } else | |
873 scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); | |
874 free_arg_lst(paramlst); | |
875 } | |
876 | |
877 // cmd_setstatus(recipient, arg) | |
878 // Set your Jabber status. | |
879 // - if recipient is not NULL, the status is sent to this contact only | |
880 // - arg must be "status message" (message is optional) | |
881 void cmd_setstatus(const char *recipient, const char *arg) | |
882 { | |
883 char **paramlst; | |
884 char *status; | |
885 char *msg; | |
886 enum imstatus st; | |
887 | |
888 if (!lm_connection_is_authenticated(lconnection)) { | |
889 scr_LogPrint(LPRINT_NORMAL, "You are not connected."); | |
890 return; | |
891 } | |
892 | |
893 // It makes sense to reset autoaway before changing the status | |
894 // (esp. for FIFO or remote commands) or the behaviour could be | |
895 // unexpected... | |
896 if (!recipient) | |
897 scr_CheckAutoAway(TRUE); | |
898 | |
899 paramlst = split_arg(arg, 2, 1); // status, message | |
900 status = *paramlst; | |
901 msg = *(paramlst+1); | |
902 | |
903 if (!status) { | |
904 free_arg_lst(paramlst); | |
905 return; | |
906 } | |
907 | |
908 if (!strcasecmp(status, IMSTATUS_OFFLINE)) st = offline; | |
909 else if (!strcasecmp(status, IMSTATUS_ONLINE)) st = available; | |
910 else if (!strcasecmp(status, IMSTATUS_AVAILABLE)) st = available; | |
911 else if (!strcasecmp(status, IMSTATUS_AWAY)) st = away; | |
912 else if (!strcasecmp(status, IMSTATUS_INVISIBLE)) st = invisible; | |
913 else if (!strcasecmp(status, IMSTATUS_DONOTDISTURB)) st = dontdisturb; | |
914 else if (!strcasecmp(status, IMSTATUS_NOTAVAILABLE)) st = notavail; | |
915 else if (!strcasecmp(status, IMSTATUS_FREE4CHAT)) st = freeforchat; | |
916 else if (!strcasecmp(status, "message")) { | |
917 if (!msg || !*msg) { | |
918 // We want a message. If there's none, we give up. | |
919 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
920 free_arg_lst(paramlst); | |
921 return; | |
922 } | |
923 st = xmpp_getstatus(); // Preserve current status | |
924 } else { | |
925 scr_LogPrint(LPRINT_NORMAL, "Unrecognized status!"); | |
926 free_arg_lst(paramlst); | |
927 return; | |
928 } | |
929 | |
930 // Use provided message | |
931 if (msg && !*msg) { | |
932 msg = NULL; | |
933 } | |
934 | |
935 // If a recipient is specified, let's don't use default status messages | |
936 if (recipient && !msg) | |
937 msg = ""; | |
938 | |
939 xmpp_setstatus(st, recipient, msg, FALSE); | |
940 | |
941 free_arg_lst(paramlst); | |
942 } | |
943 | |
944 static void do_status(char *arg) | |
945 { | |
946 if (!*arg) { | |
947 const char *sm = xmpp_getstatusmsg(); | |
948 scr_LogPrint(LPRINT_NORMAL, "Your status is: [%c] %s", | |
949 imstatus2char[xmpp_getstatus()], | |
950 (sm ? sm : "")); | |
951 return; | |
952 } | |
953 arg = to_utf8(arg); | |
954 cmd_setstatus(NULL, arg); | |
955 g_free(arg); | |
956 } | |
957 | |
958 static void do_status_to(char *arg) | |
959 { | |
960 char **paramlst; | |
961 char *fjid, *st, *msg; | |
962 char *jid_utf8 = NULL; | |
963 | |
964 paramlst = split_arg(arg, 3, 1); // jid, status, [message] | |
965 fjid = *paramlst; | |
966 st = *(paramlst+1); | |
967 msg = *(paramlst+2); | |
968 | |
969 if (!fjid || !st) { | |
970 scr_LogPrint(LPRINT_NORMAL, | |
971 "Please specify both a Jabber ID and a status."); | |
972 free_arg_lst(paramlst); | |
973 return; | |
974 } | |
975 | |
976 // Allow things like /status_to "" away | |
977 if (!*fjid || !strcmp(fjid, ".")) | |
978 fjid = NULL; | |
979 | |
980 if (fjid) { | |
981 // The JID has been specified. Quick check... | |
982 if (check_jid_syntax(fjid)) { | |
983 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
984 "<%s> is not a valid Jabber ID.", fjid); | |
985 fjid = NULL; | |
986 } else { | |
987 // Convert jid to lowercase | |
988 char *p = fjid; | |
989 for ( ; *p && *p != JID_RESOURCE_SEPARATOR; p++) | |
990 *p = tolower(*p); | |
991 fjid = jid_utf8 = to_utf8(fjid); | |
992 } | |
993 } else { | |
994 // Add the current buddy | |
995 if (current_buddy) | |
996 fjid = (char*)buddy_getjid(BUDDATA(current_buddy)); | |
997 if (!fjid) | |
998 scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID."); | |
999 } | |
1000 | |
1001 if (fjid) { | |
1002 char *cmdline; | |
1003 if (!msg) | |
1004 msg = ""; | |
1005 msg = to_utf8(msg); | |
1006 cmdline = g_strdup_printf("%s %s", st, msg); | |
1007 scr_LogPrint(LPRINT_LOGNORM, "Sending to <%s> /status %s", fjid, cmdline); | |
1008 cmd_setstatus(fjid, cmdline); | |
1009 g_free(msg); | |
1010 g_free(cmdline); | |
1011 g_free(jid_utf8); | |
1012 } | |
1013 free_arg_lst(paramlst); | |
1014 } | |
1015 | |
1016 static void do_add(char *arg) | |
1017 { | |
1018 char **paramlst; | |
1019 char *id, *nick; | |
1020 char *jid_utf8 = NULL; | |
1021 | |
1022 if (!lm_connection_is_authenticated(lconnection)) { | |
1023 scr_LogPrint(LPRINT_NORMAL, "You are not connected."); | |
1024 return; | |
1025 } | |
1026 | |
1027 paramlst = split_arg(arg, 2, 0); // jid, [nickname] | |
1028 id = *paramlst; | |
1029 nick = *(paramlst+1); | |
1030 | |
1031 if (!id) | |
1032 nick = NULL; // Allow things like: /add "" nick | |
1033 else if (!*id || !strcmp(id, ".")) | |
1034 id = NULL; | |
1035 | |
1036 if (id) { | |
1037 // The JID has been specified. Quick check... | |
1038 if (check_jid_syntax(id)) { | |
1039 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
1040 "<%s> is not a valid Jabber ID.", id); | |
1041 id = NULL; | |
1042 } else { | |
1043 mc_strtolower(id); | |
1044 // Actually an UTF-8 id isn't needed because only the bare jid will | |
1045 // be used. | |
1046 id = jid_utf8 = to_utf8(id); | |
1047 } | |
1048 } else { | |
1049 // Add the current buddy | |
1050 if (current_buddy) | |
1051 id = (char*)buddy_getjid(BUDDATA(current_buddy)); | |
1052 if (!id) | |
1053 scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID."); | |
1054 } | |
1055 | |
1056 if (nick) | |
1057 nick = to_utf8(nick); | |
1058 | |
1059 if (id) { | |
1060 // 2nd parameter = optional nickname | |
1061 xmpp_addbuddy(id, nick, NULL); | |
1062 scr_LogPrint(LPRINT_LOGNORM, "Sent presence notification request to <%s>.", | |
1063 id); | |
1064 } | |
1065 | |
1066 g_free(jid_utf8); | |
1067 g_free(nick); | |
1068 free_arg_lst(paramlst); | |
1069 } | |
1070 | |
1071 static void do_del(char *arg) | |
1072 { | |
1073 const char *bjid; | |
1074 | |
1075 if (*arg) { | |
1076 scr_LogPrint(LPRINT_NORMAL, "This action does not require a parameter; " | |
1077 "the currently-selected buddy will be deleted."); | |
1078 return; | |
1079 } | |
1080 | |
1081 if (!current_buddy) | |
1082 return; | |
1083 bjid = buddy_getjid(BUDDATA(current_buddy)); | |
1084 if (!bjid) | |
1085 return; | |
1086 | |
1087 if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_ROOM) { | |
1088 // This is a chatroom | |
1089 if (buddy_getinsideroom(BUDDATA(current_buddy))) { | |
1090 scr_LogPrint(LPRINT_NORMAL, "You haven't left this room!"); | |
1091 return; | |
1092 } | |
1093 } | |
1094 | |
1095 // Close the buffer | |
1096 scr_BufferPurge(1, NULL); | |
1097 | |
1098 scr_LogPrint(LPRINT_LOGNORM, "Removing <%s>...", bjid); | |
1099 xmpp_delbuddy(bjid); | |
1100 scr_UpdateBuddyWindow(); | |
1101 } | |
1102 | |
1103 static void do_group(char *arg) | |
1104 { | |
1105 gpointer group = NULL; | |
1106 guint leave_buddywindow; | |
1107 char **paramlst; | |
1108 char *subcmd; | |
1109 enum { group_toggle = -1, group_unfold = 0, group_fold = 1 } group_state = 0; | |
1110 | |
1111 if (!*arg) { | |
1112 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
1113 return; | |
1114 } | |
1115 | |
1116 if (!current_buddy) | |
1117 return; | |
1118 | |
1119 paramlst = split_arg(arg, 2, 0); // subcmd, [arg] | |
1120 subcmd = *paramlst; | |
1121 arg = *(paramlst+1); | |
1122 | |
1123 if (!subcmd || !*subcmd) | |
1124 goto do_group_return; // Should not happen anyway | |
1125 | |
1126 if (arg && *arg) { | |
1127 GSList *roster_elt; | |
1128 char *group_utf8 = to_utf8(arg); | |
1129 roster_elt = roster_find(group_utf8, namesearch, ROSTER_TYPE_GROUP); | |
1130 g_free(group_utf8); | |
1131 if (roster_elt) | |
1132 group = buddy_getgroup(roster_elt->data); | |
1133 } else { | |
1134 group = buddy_getgroup(BUDDATA(current_buddy)); | |
1135 } | |
1136 if (!group) | |
1137 goto do_group_return; | |
1138 | |
1139 // We'll have to redraw the chat window if we're not currently on the group | |
1140 // entry itself, because it means we'll have to leave the current buddy | |
1141 // chat window. | |
1142 leave_buddywindow = (group != BUDDATA(current_buddy) && | |
1143 group == buddy_getgroup(BUDDATA(current_buddy))); | |
1144 | |
1145 | |
1146 if (!(buddy_gettype(group) & ROSTER_TYPE_GROUP)) { | |
1147 scr_LogPrint(LPRINT_NORMAL, "You need to select a group."); | |
1148 goto do_group_return; | |
1149 } | |
1150 | |
1151 if (!strcasecmp(subcmd, "expand") || !strcasecmp(subcmd, "unfold")) | |
1152 group_state = group_unfold; | |
1153 else if (!strcasecmp(subcmd, "shrink") || !strcasecmp(subcmd, "fold")) | |
1154 group_state = group_fold; | |
1155 else if (!strcasecmp(subcmd, "toggle")) | |
1156 group_state = group_toggle; | |
1157 else { | |
1158 scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); | |
1159 goto do_group_return; | |
1160 } | |
1161 | |
1162 if (group_state != group_unfold && leave_buddywindow) | |
1163 scr_RosterPrevGroup(); | |
1164 | |
1165 buddy_hide_group(group, group_state); | |
1166 | |
1167 buddylist_build(); | |
1168 update_roster = TRUE; | |
1169 | |
1170 do_group_return: | |
1171 free_arg_lst(paramlst); | |
1172 } | |
1173 | |
1174 static int send_message_to(const char *fjid, const char *msg, const char *subj, | |
1175 LmMessageSubType type_overwrite, bool quiet) | |
1176 { | |
1177 char *bare_jid, *rp; | |
1178 char *hmsg; | |
1179 gint crypted; | |
1180 gint retval = 0; | |
1181 int isroom; | |
1182 gpointer xep184 = NULL; | |
1183 | |
1184 if (!lm_connection_is_authenticated(lconnection)) { | |
1185 scr_LogPrint(LPRINT_NORMAL, "You are not connected."); | |
1186 return 1; | |
1187 } | |
1188 if (!fjid || !*fjid) { | |
1189 scr_LogPrint(LPRINT_NORMAL, "You must specify a Jabber ID."); | |
1190 return 1; | |
1191 } | |
1192 if (!msg || !*msg) { | |
1193 scr_LogPrint(LPRINT_NORMAL, "You must specify a message."); | |
1194 return 1; | |
1195 } | |
1196 if (check_jid_syntax((char*)fjid)) { | |
1197 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
1198 "<%s> is not a valid Jabber ID.", fjid); | |
1199 return 1; | |
1200 } | |
1201 | |
1202 // We must use the bare jid in hk_message_out() | |
1203 rp = strchr(fjid, JID_RESOURCE_SEPARATOR); | |
1204 if (rp) | |
1205 bare_jid = g_strndup(fjid, rp - fjid); | |
1206 else | |
1207 bare_jid = (char*)fjid; | |
1208 | |
1209 if (!quiet) { | |
1210 // Jump to window, create one if needed | |
1211 scr_RosterJumpJid(bare_jid); | |
1212 } | |
1213 | |
1214 // Check if we're sending a message to a conference room | |
1215 // If not, we must make sure rp is NULL, for hk_message_out() | |
1216 isroom = !!roster_find(bare_jid, jidsearch, ROSTER_TYPE_ROOM); | |
1217 if (rp) { | |
1218 if (isroom) rp++; | |
1219 else rp = NULL; | |
1220 } | |
1221 isroom = isroom && (!rp || !*rp); | |
1222 | |
1223 // local part (UI, logging, etc.) | |
1224 if (subj) | |
1225 hmsg = g_strdup_printf("[%s]\n%s", subj, msg); | |
1226 else | |
1227 hmsg = (char*)msg; | |
1228 | |
1229 // Network part | |
1230 xmpp_send_msg(fjid, msg, (isroom ? ROSTER_TYPE_ROOM : ROSTER_TYPE_USER), | |
1231 subj, FALSE, &crypted, type_overwrite, &xep184); | |
1232 | |
1233 if (crypted == -1) { | |
1234 scr_LogPrint(LPRINT_LOGNORM, "Encryption error. Message was not sent."); | |
1235 retval = 1; | |
1236 goto send_message_to_return; | |
1237 } | |
1238 | |
1239 // Hook | |
1240 if (!isroom) | |
1241 hk_message_out(bare_jid, rp, 0, hmsg, crypted, xep184); | |
1242 | |
1243 send_message_to_return: | |
1244 if (hmsg != msg) g_free(hmsg); | |
1245 if (rp) g_free(bare_jid); | |
1246 return retval; | |
1247 } | |
1248 | |
1249 // send_message(msg, subj, type_overwrite) | |
1250 // Write the message in the buddy's window and send the message on | |
1251 // the network. | |
1252 static void send_message(const char *msg, const char *subj, | |
1253 LmMessageSubType type_overwrite) | |
1254 { | |
1255 const char *bjid; | |
1256 | |
1257 if (!current_buddy) { | |
1258 scr_LogPrint(LPRINT_NORMAL, "No buddy is currently selected."); | |
1259 return; | |
1260 } | |
1261 | |
1262 bjid = CURRENT_JID; | |
1263 if (!bjid) { | |
1264 scr_LogPrint(LPRINT_NORMAL, "No buddy is currently selected."); | |
1265 return; | |
1266 } | |
1267 | |
1268 send_message_to(bjid, msg, subj, type_overwrite, FALSE); | |
1269 } | |
1270 | |
1271 static LmMessageSubType scan_mtype(char **arg) | |
1272 { | |
1273 //Try splitting it | |
1274 char **parlist = split_arg(*arg, 2, 1); | |
1275 LmMessageSubType result = LM_MESSAGE_SUB_TYPE_NOT_SET; | |
1276 //Is it any good parameter? | |
1277 if (parlist && *parlist) { | |
1278 if (!strcmp("-n", *parlist)) { | |
1279 result = LM_MESSAGE_SUB_TYPE_NORMAL; | |
1280 } else if (!strcmp("-h", *parlist)) { | |
1281 result = LM_MESSAGE_SUB_TYPE_HEADLINE; | |
1282 } | |
1283 if (result != LM_MESSAGE_SUB_TYPE_NOT_SET || (!strcmp("--", *parlist))) | |
1284 *arg += strlen(*arg) - (parlist[1] ? strlen(parlist[1]) : 0); | |
1285 } | |
1286 //Anything found? -> skip it | |
1287 free_arg_lst(parlist); | |
1288 return result; | |
1289 } | |
1290 | |
1291 static void do_say_internal(char *arg, int parse_flags) | |
1292 { | |
1293 gpointer bud; | |
1294 LmMessageSubType msgtype = LM_MESSAGE_SUB_TYPE_NOT_SET; | |
1295 | |
1296 scr_set_chatmode(TRUE); | |
1297 scr_ShowBuddyWindow(); | |
1298 | |
1299 if (!current_buddy) { | |
1300 scr_LogPrint(LPRINT_NORMAL, | |
1301 "Whom are you talking to? Please select a buddy."); | |
1302 return; | |
1303 } | |
1304 | |
1305 bud = BUDDATA(current_buddy); | |
1306 if (!(buddy_gettype(bud) & | |
1307 (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM))) { | |
1308 scr_LogPrint(LPRINT_NORMAL, "This is not a user."); | |
1309 return; | |
1310 } | |
1311 | |
1312 buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE); | |
1313 if (parse_flags) | |
1314 msgtype = scan_mtype(&arg); | |
1315 arg = to_utf8(arg); | |
1316 send_message(arg, NULL, msgtype); | |
1317 g_free(arg); | |
1318 } | |
1319 | |
1320 static void do_say(char *arg) { | |
1321 do_say_internal(arg, 1); | |
1322 } | |
1323 | |
1324 static void do_msay(char *arg) | |
1325 { | |
1326 /* Parameters: begin verbatim abort send send_to */ | |
1327 char **paramlst; | |
1328 char *subcmd; | |
1329 | |
1330 paramlst = split_arg(arg, 2, 1); // subcmd, arg | |
1331 subcmd = *paramlst; | |
1332 arg = *(paramlst+1); | |
1333 | |
1334 if (!subcmd || !*subcmd) { | |
1335 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
1336 scr_LogPrint(LPRINT_NORMAL, "Please read the manual before using " | |
1337 "the /msay command."); | |
1338 scr_LogPrint(LPRINT_NORMAL, "(Use \"%s begin\" to enter " | |
1339 "multi-line mode...)", mkcmdstr("msay")); | |
1340 goto do_msay_return; | |
1341 } | |
1342 | |
1343 if (!strcasecmp(subcmd, "toggle")) { | |
1344 if (scr_get_multimode()) | |
1345 subcmd = "send"; | |
1346 else | |
1347 subcmd = "begin"; | |
1348 } else if (!strcasecmp(subcmd, "toggle_verbatim")) { | |
1349 if (scr_get_multimode()) | |
1350 subcmd = "send"; | |
1351 else | |
1352 subcmd = "verbatim"; | |
1353 } | |
1354 | |
1355 if (!strcasecmp(subcmd, "abort")) { | |
1356 if (scr_get_multimode()) | |
1357 scr_LogPrint(LPRINT_NORMAL, "Leaving multi-line message mode."); | |
1358 scr_set_multimode(FALSE, NULL); | |
1359 goto do_msay_return; | |
1360 } else if ((!strcasecmp(subcmd, "begin")) || | |
1361 (!strcasecmp(subcmd, "verbatim"))) { | |
1362 bool verbat; | |
1363 gchar *subj_utf8 = to_utf8(arg); | |
1364 if (!strcasecmp(subcmd, "verbatim")) { | |
1365 scr_set_multimode(2, subj_utf8); | |
1366 verbat = TRUE; | |
1367 } else { | |
1368 scr_set_multimode(1, subj_utf8); | |
1369 verbat = FALSE; | |
1370 } | |
1371 | |
1372 scr_LogPrint(LPRINT_NORMAL, "Entered %smulti-line message mode.", | |
1373 verbat ? "VERBATIM " : ""); | |
1374 scr_LogPrint(LPRINT_NORMAL, "Select a buddy and use \"%s send\" " | |
1375 "when your message is ready.", mkcmdstr("msay")); | |
1376 if (verbat) | |
1377 scr_LogPrint(LPRINT_NORMAL, "Use \"%s abort\" to abort this mode.", | |
1378 mkcmdstr("msay")); | |
1379 g_free(subj_utf8); | |
1380 goto do_msay_return; | |
1381 } else if (strcasecmp(subcmd, "send") && strcasecmp(subcmd, "send_to")) { | |
1382 scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); | |
1383 goto do_msay_return; | |
1384 } | |
1385 | |
1386 /* send/send_to command */ | |
1387 | |
1388 if (!scr_get_multimode()) { | |
1389 scr_LogPrint(LPRINT_NORMAL, "No message to send. " | |
1390 "Use \"%s begin\" first.", mkcmdstr("msay")); | |
1391 goto do_msay_return; | |
1392 } | |
1393 | |
1394 scr_set_chatmode(TRUE); | |
1395 scr_ShowBuddyWindow(); | |
1396 | |
1397 if (!strcasecmp(subcmd, "send_to")) { | |
1398 int err = FALSE; | |
1399 gchar *msg_utf8; | |
1400 LmMessageSubType msg_type = scan_mtype(&arg); | |
1401 // Let's send to the specified JID. We leave now if there | |
1402 // has been an error (so we don't leave multi-line mode). | |
1403 arg = to_utf8(arg); | |
1404 msg_utf8 = to_utf8(scr_get_multiline()); | |
1405 if (msg_utf8) { | |
1406 err = send_message_to(arg, msg_utf8, scr_get_multimode_subj(), msg_type, | |
1407 FALSE); | |
1408 g_free(msg_utf8); | |
1409 } | |
1410 g_free(arg); | |
1411 if (err) | |
1412 goto do_msay_return; | |
1413 } else { // Send to currently selected buddy | |
1414 gpointer bud; | |
1415 gchar *msg_utf8; | |
1416 | |
1417 if (!current_buddy) { | |
1418 scr_LogPrint(LPRINT_NORMAL, "Whom are you talking to?"); | |
1419 goto do_msay_return; | |
1420 } | |
1421 | |
1422 bud = BUDDATA(current_buddy); | |
1423 if (!(buddy_gettype(bud) & | |
1424 (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM))) { | |
1425 scr_LogPrint(LPRINT_NORMAL, "This is not a user."); | |
1426 goto do_msay_return; | |
1427 } | |
1428 | |
1429 buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE); | |
1430 msg_utf8 = to_utf8(scr_get_multiline()); | |
1431 if (msg_utf8) { | |
1432 send_message(msg_utf8, scr_get_multimode_subj(), scan_mtype(&arg)); | |
1433 g_free(msg_utf8); | |
1434 } | |
1435 } | |
1436 scr_set_multimode(FALSE, NULL); | |
1437 scr_LogPrint(LPRINT_NORMAL, "You have left multi-line message mode."); | |
1438 do_msay_return: | |
1439 free_arg_lst(paramlst); | |
1440 } | |
1441 | |
1442 // load_message_from_file(filename) | |
1443 // Read the whole content of a file. | |
1444 // The data are converted to UTF8, they should be freed by the caller after | |
1445 // use. | |
1446 char *load_message_from_file(const char *filename) | |
1447 { | |
1448 FILE *fd; | |
1449 struct stat buf; | |
1450 char *msgbuf, *msgbuf_utf8; | |
1451 char *p; | |
1452 char *next_utf8_char; | |
1453 size_t len; | |
1454 | |
1455 fd = fopen(filename, "r"); | |
1456 | |
1457 if (!fd || fstat(fileno(fd), &buf)) { | |
1458 scr_LogPrint(LPRINT_LOGNORM, "Cannot open message file (%s)", filename); | |
1459 return NULL; | |
1460 } | |
1461 if (!buf.st_size || buf.st_size >= HBB_BLOCKSIZE) { | |
1462 if (!buf.st_size) | |
1463 scr_LogPrint(LPRINT_LOGNORM, "Message file is empty (%s)", filename); | |
1464 else | |
1465 scr_LogPrint(LPRINT_LOGNORM, "Message file is too big (%s)", filename); | |
1466 fclose(fd); | |
1467 return NULL; | |
1468 } | |
1469 | |
1470 msgbuf = g_new0(char, HBB_BLOCKSIZE); | |
1471 len = fread(msgbuf, 1, HBB_BLOCKSIZE-1, fd); | |
1472 fclose(fd); | |
1473 | |
1474 next_utf8_char = msgbuf; | |
1475 | |
1476 // Check there is no binary data. It must be a *message* file! | |
1477 for (p = msgbuf ; *p ; p++) { | |
1478 if (utf8_mode) { | |
1479 if (p == next_utf8_char) { | |
1480 if (!iswprint(get_char(p)) && *p != '\n' && *p != '\t') | |
1481 break; | |
1482 next_utf8_char = next_char(p); | |
1483 } | |
1484 } else { | |
1485 unsigned char sc = *p; | |
1486 if (!iswprint(sc) && sc != '\n' && sc != '\t') | |
1487 break; | |
1488 } | |
1489 } | |
1490 | |
1491 if (*p || (size_t)(p-msgbuf) != len) { // We're not at the End Of Line... | |
1492 scr_LogPrint(LPRINT_LOGNORM, "Message file contains " | |
1493 "invalid characters (%s)", filename); | |
1494 g_free(msgbuf); | |
1495 return NULL; | |
1496 } | |
1497 | |
1498 // p is now at the EOL | |
1499 // Let's strip trailing newlines | |
1500 if (p > msgbuf) | |
1501 p--; | |
1502 while (p > msgbuf && *p == '\n') | |
1503 *p-- = 0; | |
1504 | |
1505 // It could be empty, once the trailing newlines are gone | |
1506 if (p == msgbuf && *p == '\n') { | |
1507 scr_LogPrint(LPRINT_LOGNORM, "Message file is empty (%s)", filename); | |
1508 g_free(msgbuf); | |
1509 return NULL; | |
1510 } | |
1511 | |
1512 msgbuf_utf8 = to_utf8(msgbuf); | |
1513 | |
1514 if (!msgbuf_utf8 && msgbuf) | |
1515 scr_LogPrint(LPRINT_LOGNORM, "Message file charset conversion error (%s)", | |
1516 filename); | |
1517 g_free(msgbuf); | |
1518 return msgbuf_utf8; | |
1519 } | |
1520 | |
1521 static void do_say_to(char *arg) | |
1522 { | |
1523 char **paramlst; | |
1524 char *fjid, *msg; | |
1525 char *file = NULL; | |
1526 LmMessageSubType msg_type = LM_MESSAGE_SUB_TYPE_NOT_SET; | |
1527 bool quiet = FALSE; | |
1528 | |
1529 if (!lm_connection_is_authenticated(lconnection)) { | |
1530 scr_LogPrint(LPRINT_NORMAL, "You are not connected."); | |
1531 return; | |
1532 } | |
1533 | |
1534 msg_type = scan_mtype(&arg); | |
1535 paramlst = split_arg(arg, 2, 1); // jid, message (or option, jid, message) | |
1536 | |
1537 if (!*paramlst) { // No parameter? | |
1538 scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID."); | |
1539 free_arg_lst(paramlst); | |
1540 return; | |
1541 } | |
1542 | |
1543 // Check for an option parameter | |
1544 while (*paramlst) { | |
1545 if (!strcmp(*paramlst, "-q")) { | |
1546 char **oldparamlst = paramlst; | |
1547 paramlst = split_arg(*(oldparamlst+1), 2, 1); // jid, message | |
1548 free_arg_lst(oldparamlst); | |
1549 quiet = TRUE; | |
1550 } else if (!strcmp(*paramlst, "-f")) { | |
1551 char **oldparamlst = paramlst; | |
1552 paramlst = split_arg(*(oldparamlst+1), 2, 1); // filename, jid | |
1553 free_arg_lst(oldparamlst); | |
1554 if (!*paramlst) { | |
1555 scr_LogPrint(LPRINT_NORMAL, "Wrong usage."); | |
1556 return; | |
1557 } | |
1558 file = g_strdup(*paramlst); | |
1559 // One more parameter shift... | |
1560 oldparamlst = paramlst; | |
1561 paramlst = split_arg(*(oldparamlst+1), 2, 1); // jid, nothing | |
1562 free_arg_lst(oldparamlst); | |
1563 } else | |
1564 break; | |
1565 } | |
1566 | |
1567 if (!*paramlst) { | |
1568 scr_LogPrint(LPRINT_NORMAL, "Wrong usage."); | |
1569 return; | |
1570 } | |
1571 | |
1572 fjid = *paramlst; | |
1573 msg = *(paramlst+1); | |
1574 | |
1575 if (!strcmp(fjid, ".")) { | |
1576 // Send the message to the current buddy | |
1577 if (current_buddy) | |
1578 fjid = (char*)buddy_getjid(BUDDATA(current_buddy)); | |
1579 if (!fjid) { | |
1580 scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID."); | |
1581 free_arg_lst(paramlst); | |
1582 return; | |
1583 } | |
1584 } else if (check_jid_syntax(fjid)) { | |
1585 scr_LogPrint(LPRINT_NORMAL, "Please specify a valid Jabber ID."); | |
1586 free_arg_lst(paramlst); | |
1587 return; | |
1588 } | |
1589 | |
1590 fjid = to_utf8(fjid); | |
1591 if (!file) { | |
1592 msg = to_utf8(msg); | |
1593 } else { | |
1594 char *filename_xp; | |
1595 if (msg) | |
1596 scr_LogPrint(LPRINT_NORMAL, "say_to: extra parameter ignored."); | |
1597 filename_xp = expand_filename(file); | |
1598 msg = load_message_from_file(filename_xp); | |
1599 g_free(filename_xp); | |
1600 g_free(file); | |
1601 } | |
1602 | |
1603 send_message_to(fjid, msg, NULL, msg_type, quiet); | |
1604 | |
1605 g_free(fjid); | |
1606 g_free(msg); | |
1607 free_arg_lst(paramlst); | |
1608 } | |
1609 | |
1610 // buffer_updown(updown, nblines) | |
1611 // updown: -1=up, +1=down | |
1612 inline static void buffer_updown(int updown, char *nlines) | |
1613 { | |
1614 int nblines; | |
1615 | |
1616 if (!nlines || !*nlines) | |
1617 nblines = 0; | |
1618 else | |
1619 nblines = strtol(nlines, NULL, 10); | |
1620 | |
1621 if (nblines >= 0) | |
1622 scr_BufferScrollUpDown(updown, nblines); | |
1623 } | |
1624 | |
1625 static void buffer_search(int direction, char *arg) | |
1626 { | |
1627 if (!arg || !*arg) { | |
1628 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
1629 return; | |
1630 } | |
1631 | |
1632 scr_BufferSearch(direction, arg); | |
1633 } | |
1634 | |
1635 static void buffer_date(char *date) | |
1636 { | |
1637 time_t t; | |
1638 | |
1639 if (!date || !*date) { | |
1640 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
1641 return; | |
1642 } | |
1643 | |
1644 strip_arg_special_chars(date); | |
1645 | |
1646 t = from_iso8601(date, 0); | |
1647 if (t) | |
1648 scr_BufferDate(t); | |
1649 else | |
1650 scr_LogPrint(LPRINT_NORMAL, "The date you specified is " | |
1651 "not correctly formatted or invalid."); | |
1652 } | |
1653 | |
1654 static void buffer_percent(char *arg1, char *arg2) | |
1655 { | |
1656 // Basically, user has typed "%arg1 arg2" | |
1657 // "%50" -> arg1 = 50, arg2 null pointer | |
1658 // "% 50" -> arg1 = \0, arg2 = 50 | |
1659 | |
1660 if (!*arg1 && (!arg2 || !*arg2)) { // No value | |
1661 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
1662 return; | |
1663 } | |
1664 | |
1665 if (*arg1 && arg2 && *arg2) { // Two values | |
1666 scr_LogPrint(LPRINT_NORMAL, "Wrong parameters."); | |
1667 return; | |
1668 } | |
1669 | |
1670 scr_BufferPercent(atoi((*arg1 ? arg1 : arg2))); | |
1671 } | |
1672 | |
1673 static void do_buffer(char *arg) | |
1674 { | |
1675 char **paramlst; | |
1676 char *subcmd; | |
1677 | |
1678 if (!current_buddy) | |
1679 return; | |
1680 | |
1681 paramlst = split_arg(arg, 2, 1); // subcmd, arg | |
1682 subcmd = *paramlst; | |
1683 arg = *(paramlst+1); | |
1684 | |
1685 if (!subcmd || !*subcmd) { | |
1686 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
1687 free_arg_lst(paramlst); | |
1688 return; | |
1689 } | |
1690 | |
1691 if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP && | |
1692 strcasecmp(subcmd, "close_all")) { | |
1693 scr_LogPrint(LPRINT_NORMAL, "Groups have no buffer."); | |
1694 free_arg_lst(paramlst); | |
1695 return; | |
1696 } | |
1697 | |
1698 if (!strcasecmp(subcmd, "top")) { | |
1699 scr_BufferTopBottom(-1); | |
1700 } else if (!strcasecmp(subcmd, "bottom")) { | |
1701 scr_BufferTopBottom(1); | |
1702 } else if (!strcasecmp(subcmd, "clear")) { | |
1703 scr_BufferClear(); | |
1704 } else if (!strcasecmp(subcmd, "close")) { | |
1705 scr_BufferPurge(1, arg); | |
1706 } else if (!strcasecmp(subcmd, "close_all")) { | |
1707 scr_BufferPurgeAll(1); | |
1708 } else if (!strcasecmp(subcmd, "purge")) { | |
1709 scr_BufferPurge(0, arg); | |
1710 } else if (!strcasecmp(subcmd, "scroll_lock")) { | |
1711 scr_BufferScrollLock(1); | |
1712 } else if (!strcasecmp(subcmd, "scroll_unlock")) { | |
1713 scr_BufferScrollLock(0); | |
1714 } else if (!strcasecmp(subcmd, "scroll_toggle")) { | |
1715 scr_BufferScrollLock(-1); | |
1716 } else if (!strcasecmp(subcmd, "up")) { | |
1717 buffer_updown(-1, arg); | |
1718 } else if (!strcasecmp(subcmd, "down")) { | |
1719 buffer_updown(1, arg); | |
1720 } else if (!strcasecmp(subcmd, "search_backward")) { | |
1721 strip_arg_special_chars(arg); | |
1722 buffer_search(-1, arg); | |
1723 } else if (!strcasecmp(subcmd, "search_forward")) { | |
1724 strip_arg_special_chars(arg); | |
1725 buffer_search(1, arg); | |
1726 } else if (!strcasecmp(subcmd, "date")) { | |
1727 buffer_date(arg); | |
1728 } else if (*subcmd == '%') { | |
1729 buffer_percent(subcmd+1, arg); | |
1730 } else if (!strcasecmp(subcmd, "save")) { | |
1731 scr_BufferDump(arg); | |
1732 } else if (!strcasecmp(subcmd, "list")) { | |
1733 scr_BufferList(); | |
1734 } else { | |
1735 scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); | |
1736 } | |
1737 | |
1738 free_arg_lst(paramlst); | |
1739 } | |
1740 | |
1741 static void do_clear(char *arg) // Alias for "buffer clear" | |
1742 { | |
1743 do_buffer("clear"); | |
1744 } | |
1745 | |
1746 static void do_info(char *arg) | |
1747 { | |
1748 gpointer bud; | |
1749 const char *bjid, *name; | |
1750 guint type, on_srv; | |
1751 char *buffer; | |
1752 enum subscr esub; | |
1753 | |
1754 if (!current_buddy) | |
1755 return; | |
1756 bud = BUDDATA(current_buddy); | |
1757 | |
1758 bjid = buddy_getjid(bud); | |
1759 name = buddy_getname(bud); | |
1760 type = buddy_gettype(bud); | |
1761 esub = buddy_getsubscription(bud); | |
1762 on_srv = buddy_getonserverflag(bud); | |
1763 | |
1764 buffer = g_new(char, 4096); | |
1765 | |
1766 if (bjid) { | |
1767 GSList *resources, *p_res; | |
1768 char *bstr = "unknown"; | |
1769 | |
1770 // Enter chat mode | |
1771 scr_set_chatmode(TRUE); | |
1772 scr_ShowBuddyWindow(); | |
1773 | |
1774 snprintf(buffer, 4095, "jid: <%s>", bjid); | |
1775 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1776 if (name) { | |
1777 snprintf(buffer, 4095, "Name: %s", name); | |
1778 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1779 } | |
1780 | |
1781 if (type == ROSTER_TYPE_USER) bstr = "user"; | |
1782 else if (type == ROSTER_TYPE_ROOM) bstr = "chatroom"; | |
1783 else if (type == ROSTER_TYPE_AGENT) bstr = "agent"; | |
1784 snprintf(buffer, 127, "Type: %s", bstr); | |
1785 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1786 | |
1787 if (!on_srv) { | |
1788 scr_WriteIncomingMessage(bjid, "(Local item, not on the server)", | |
1789 0, HBB_PREFIX_INFO, 0); | |
1790 } | |
1791 | |
1792 if (esub == sub_both) bstr = "both"; | |
1793 else if (esub & sub_from) bstr = "from"; | |
1794 else if (esub & sub_to) bstr = "to"; | |
1795 else bstr = "none"; | |
1796 snprintf(buffer, 64, "Subscription: %s", bstr); | |
1797 if (esub & sub_pending) | |
1798 strcat(buffer, " (pending)"); | |
1799 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1800 | |
1801 resources = buddy_getresources(bud); | |
1802 if (!resources && type == ROSTER_TYPE_USER) { | |
1803 // No resource; display last status message, if any. | |
1804 const char *rst_msg = buddy_getstatusmsg(bud, ""); | |
1805 if (rst_msg) { | |
1806 snprintf(buffer, 4095, "Last status message: %s", rst_msg); | |
1807 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1808 } | |
1809 } | |
1810 for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) { | |
1811 gchar rprio; | |
1812 enum imstatus rstatus; | |
1813 const char *rst_msg; | |
1814 time_t rst_time; | |
1815 struct pgp_data *rpgp; | |
1816 | |
1817 rprio = buddy_getresourceprio(bud, p_res->data); | |
1818 rstatus = buddy_getstatus(bud, p_res->data); | |
1819 rst_msg = buddy_getstatusmsg(bud, p_res->data); | |
1820 rst_time = buddy_getstatustime(bud, p_res->data); | |
1821 rpgp = buddy_resource_pgp(bud, p_res->data); | |
1822 | |
1823 snprintf(buffer, 4095, "Resource: [%c] (%d) %s", imstatus2char[rstatus], | |
1824 rprio, (char*)p_res->data); | |
1825 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1826 if (rst_msg) { | |
1827 snprintf(buffer, 4095, "Status message: %s", rst_msg); | |
1828 scr_WriteIncomingMessage(bjid, buffer, | |
1829 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); | |
1830 } | |
1831 if (rst_time) { | |
1832 char tbuf[128]; | |
1833 | |
1834 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", localtime(&rst_time)); | |
1835 snprintf(buffer, 127, "Status timestamp: %s", tbuf); | |
1836 scr_WriteIncomingMessage(bjid, buffer, | |
1837 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); | |
1838 } | |
1839 #ifdef HAVE_GPGME | |
1840 if (rpgp && rpgp->sign_keyid) { | |
1841 snprintf(buffer, 4095, "PGP key id: %s", rpgp->sign_keyid); | |
1842 scr_WriteIncomingMessage(bjid, buffer, | |
1843 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); | |
1844 if (rpgp->last_sigsum) { | |
1845 gpgme_sigsum_t ss = rpgp->last_sigsum; | |
1846 snprintf(buffer, 4095, "Last PGP signature: %s", | |
1847 (ss & GPGME_SIGSUM_GREEN ? "good": | |
1848 (ss & GPGME_SIGSUM_RED ? "bad" : "unknown"))); | |
1849 scr_WriteIncomingMessage(bjid, buffer, | |
1850 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); | |
1851 } | |
1852 } | |
1853 #endif | |
1854 g_free(p_res->data); | |
1855 } | |
1856 g_slist_free(resources); | |
1857 } else { /* Item has no jid */ | |
1858 if (name) scr_LogPrint(LPRINT_NORMAL, "Name: %s", name); | |
1859 scr_LogPrint(LPRINT_NORMAL, "Type: %s", | |
1860 type == ROSTER_TYPE_GROUP ? "group" : | |
1861 (type == ROSTER_TYPE_SPECIAL ? "special" : "unknown")); | |
1862 } | |
1863 g_free(buffer); | |
1864 | |
1865 // Tell the user if this item has an annotation. | |
1866 if (type == ROSTER_TYPE_USER || | |
1867 type == ROSTER_TYPE_ROOM || | |
1868 type == ROSTER_TYPE_AGENT) { | |
1869 struct annotation *note = xmpp_get_storage_rosternotes(bjid, TRUE); | |
1870 if (note) { | |
1871 // We do not display the note, we just tell the user. | |
1872 g_free(note->text); | |
1873 g_free(note->jid); | |
1874 g_free(note); | |
1875 scr_WriteIncomingMessage(bjid, "(This item has an annotation)", 0, | |
1876 HBB_PREFIX_INFO, 0); | |
1877 } | |
1878 } | |
1879 } | |
1880 | |
1881 // room_names() is a variation of do_info(), for chatrooms only | |
1882 static void room_names(gpointer bud, char *arg) | |
1883 { | |
1884 const char *bjid; | |
1885 char *buffer; | |
1886 GSList *resources, *p_res; | |
1887 enum { style_normal = 0, style_detail, style_short, | |
1888 style_quiet, style_compact } style = 0; | |
1889 | |
1890 if (*arg) { | |
1891 if (!strcasecmp(arg, "--short")) | |
1892 style = style_short; | |
1893 else if (!strcasecmp(arg, "--quiet")) | |
1894 style = style_quiet; | |
1895 else if (!strcasecmp(arg, "--detail")) | |
1896 style = style_detail; | |
1897 else if (!strcasecmp(arg, "--compact")) | |
1898 style = style_compact; | |
1899 else { | |
1900 scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); | |
1901 return; | |
1902 } | |
1903 } | |
1904 | |
1905 // Enter chat mode | |
1906 scr_set_chatmode(TRUE); | |
1907 scr_ShowBuddyWindow(); | |
1908 | |
1909 bjid = buddy_getjid(bud); | |
1910 | |
1911 buffer = g_new(char, 4096); | |
1912 strncpy(buffer, "Room members:", 127); | |
1913 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1914 | |
1915 resources = buddy_getresources(bud); | |
1916 for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) { | |
1917 enum imstatus rstatus; | |
1918 const char *rst_msg; | |
1919 | |
1920 rstatus = buddy_getstatus(bud, p_res->data); | |
1921 rst_msg = buddy_getstatusmsg(bud, p_res->data); | |
1922 | |
1923 if (style == style_short) { | |
1924 snprintf(buffer, 4095, "[%c] %s%s%s", imstatus2char[rstatus], | |
1925 (char*)p_res->data, | |
1926 rst_msg ? " -- " : "", rst_msg ? rst_msg : ""); | |
1927 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1928 } else if (style == style_compact) { | |
1929 enum imrole role = buddy_getrole(bud, p_res->data); | |
1930 enum imaffiliation affil = buddy_getaffil(bud, p_res->data); | |
1931 bool showaffil = (affil != affil_none); | |
1932 | |
1933 snprintf(buffer, 4095, "[%c] %s (%s%s%s)", | |
1934 imstatus2char[rstatus], (char*)p_res->data, | |
1935 showaffil ? straffil[affil] : "\0", | |
1936 showaffil ? "/" : "\0", | |
1937 strrole[role]); | |
1938 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1939 } else { | |
1940 // (Style "normal", "detail" or "quiet") | |
1941 snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus], | |
1942 (char*)p_res->data); | |
1943 scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0); | |
1944 if (rst_msg && style != style_quiet) { | |
1945 snprintf(buffer, 4095, "Status message: %s", rst_msg); | |
1946 scr_WriteIncomingMessage(bjid, buffer, | |
1947 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); | |
1948 } | |
1949 if (style == style_detail) { | |
1950 enum imrole role = buddy_getrole(bud, p_res->data); | |
1951 enum imaffiliation affil = buddy_getaffil(bud, p_res->data); | |
1952 | |
1953 snprintf(buffer, 4095, "Role: %s", strrole[role]); | |
1954 scr_WriteIncomingMessage(bjid, buffer, | |
1955 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); | |
1956 if (affil != affil_none) { | |
1957 snprintf(buffer, 4095, "Affiliat.: %s", straffil[affil]); | |
1958 scr_WriteIncomingMessage(bjid, buffer, | |
1959 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); | |
1960 } | |
1961 } | |
1962 } | |
1963 g_free(p_res->data); | |
1964 } | |
1965 g_slist_free(resources); | |
1966 g_free(buffer); | |
1967 } | |
1968 | |
1969 static void move_group_member(gpointer bud, void *groupnamedata) | |
1970 { | |
1971 const char *bjid, *name, *groupname; | |
1972 | |
1973 groupname = (char *)groupnamedata; | |
1974 | |
1975 bjid = buddy_getjid(bud); | |
1976 name = buddy_getname(bud); | |
1977 | |
1978 xmpp_updatebuddy(bjid, name, *groupname ? groupname : NULL); | |
1979 } | |
1980 | |
1981 static void do_rename(char *arg) | |
1982 { | |
1983 gpointer bud; | |
1984 const char *bjid, *group; | |
1985 guint type, on_srv; | |
1986 char *newname, *p; | |
1987 char *name_utf8; | |
1988 | |
1989 if (!current_buddy) | |
1990 return; | |
1991 bud = BUDDATA(current_buddy); | |
1992 | |
1993 bjid = buddy_getjid(bud); | |
1994 group = buddy_getgroupname(bud); | |
1995 type = buddy_gettype(bud); | |
1996 on_srv = buddy_getonserverflag(bud); | |
1997 | |
1998 if (type & ROSTER_TYPE_SPECIAL) { | |
1999 scr_LogPrint(LPRINT_NORMAL, "You can't rename this item."); | |
2000 return; | |
2001 } | |
2002 | |
2003 if (!*arg && !(type & ROSTER_TYPE_GROUP)) { | |
2004 scr_LogPrint(LPRINT_NORMAL, "Please specify a new name."); | |
2005 return; | |
2006 } | |
2007 | |
2008 if (!(type & ROSTER_TYPE_GROUP) && !on_srv) { | |
2009 scr_LogPrint(LPRINT_NORMAL, | |
2010 "Note: this item will be added to your server roster."); | |
2011 // If this is a MUC room w/o bookmark, let's give a small hint... | |
2012 if ((type & ROSTER_TYPE_ROOM) && !xmpp_is_bookmarked(bjid)) { | |
2013 scr_LogPrint(LPRINT_NORMAL, | |
2014 "You should add a room bookmark or it will not be " | |
2015 "recognized as a MUC room next time you run mcabber."); | |
2016 } | |
2017 } | |
2018 | |
2019 newname = g_strdup(arg); | |
2020 // Remove trailing space | |
2021 for (p = newname; *p; p++) ; | |
2022 while (p > newname && *p == ' ') *p = 0; | |
2023 | |
2024 strip_arg_special_chars(newname); | |
2025 | |
2026 name_utf8 = to_utf8(newname); | |
2027 | |
2028 if (type & ROSTER_TYPE_GROUP) { | |
2029 // Rename a whole group | |
2030 foreach_group_member(bud, &move_group_member, name_utf8); | |
2031 // Let's jump to the previous buddy, because this group name should | |
2032 // disappear when we receive the server answer. | |
2033 scr_RosterUpDown(-1, 1); | |
2034 } else { | |
2035 // Rename a single buddy | |
2036 guint del_name = 0; | |
2037 if (!*newname || !strcmp(arg, "-")) | |
2038 del_name = TRUE; | |
2039 buddy_setname(bud, (del_name ? (char*)bjid : name_utf8)); | |
2040 xmpp_updatebuddy(bjid, (del_name ? NULL : name_utf8), group); | |
2041 } | |
2042 | |
2043 g_free(name_utf8); | |
2044 g_free(newname); | |
2045 update_roster = TRUE; | |
2046 } | |
2047 | |
2048 static void do_move(char *arg) | |
2049 { | |
2050 gpointer bud; | |
2051 const char *bjid, *name, *oldgroupname; | |
2052 guint type; | |
2053 char *newgroupname, *p; | |
2054 char *group_utf8; | |
2055 | |
2056 if (!current_buddy) | |
2057 return; | |
2058 bud = BUDDATA(current_buddy); | |
2059 | |
2060 bjid = buddy_getjid(bud); | |
2061 name = buddy_getname(bud); | |
2062 type = buddy_gettype(bud); | |
2063 | |
2064 oldgroupname = buddy_getgroupname(bud); | |
2065 | |
2066 if (type & ROSTER_TYPE_GROUP) { | |
2067 scr_LogPrint(LPRINT_NORMAL, "You can't move groups!"); | |
2068 return; | |
2069 } | |
2070 if (type & ROSTER_TYPE_SPECIAL) { | |
2071 scr_LogPrint(LPRINT_NORMAL, "You can't move this item."); | |
2072 return; | |
2073 } | |
2074 | |
2075 newgroupname = g_strdup(arg); | |
2076 // Remove trailing space | |
2077 for (p = newgroupname; *p; p++) ; | |
2078 while (p > newgroupname && *p == ' ') *p-- = 0; | |
2079 | |
2080 strip_arg_special_chars(newgroupname); | |
2081 | |
2082 group_utf8 = to_utf8(newgroupname); | |
2083 if (strcmp(oldgroupname, group_utf8)) { | |
2084 guint msgflag; | |
2085 | |
2086 xmpp_updatebuddy(bjid, name, *group_utf8 ? group_utf8 : NULL); | |
2087 scr_RosterUpDown(-1, 1); | |
2088 | |
2089 // If the buddy has a pending message flag, | |
2090 // we remove it temporarily in order to reset the global group | |
2091 // flag. We set it back once the buddy is in the new group, | |
2092 // which will update the new group's flag. | |
2093 msgflag = buddy_getflags(bud) & ROSTER_FLAG_MSG; | |
2094 if (msgflag) | |
2095 roster_msg_setflag(bjid, FALSE, FALSE); | |
2096 buddy_setgroup(bud, group_utf8); | |
2097 if (msgflag) | |
2098 roster_msg_setflag(bjid, FALSE, TRUE); | |
2099 } | |
2100 | |
2101 g_free(group_utf8); | |
2102 g_free(newgroupname); | |
2103 update_roster = TRUE; | |
2104 } | |
2105 | |
2106 static void print_option_cb(char *k, char *v, void *f) | |
2107 { | |
2108 char *format = (char *)f; | |
2109 scr_LogPrint (LPRINT_NORMAL, format, k, v); | |
2110 } | |
2111 | |
2112 static void do_set(char *arg) | |
2113 { | |
2114 guint assign; | |
2115 gchar *option, *value; | |
2116 gchar *option_utf8; | |
2117 | |
2118 if (!*arg) { | |
2119 // list all set options | |
2120 settings_foreach(SETTINGS_TYPE_OPTION, print_option_cb, "%s = [%s]"); | |
2121 return; | |
2122 } | |
2123 | |
2124 assign = parse_assigment(arg, &option, &value); | |
2125 if (!option) { | |
2126 scr_LogPrint(LPRINT_NORMAL, "Set what option?"); | |
2127 return; | |
2128 } | |
2129 option_utf8 = to_utf8(option); | |
2130 g_free(option); | |
2131 if (!assign) { // This is a query | |
2132 const char *val = settings_opt_get(option_utf8); | |
2133 if (val) | |
2134 scr_LogPrint(LPRINT_NORMAL, "%s = [%s]", option_utf8, val); | |
2135 else | |
2136 scr_LogPrint(LPRINT_NORMAL, "Option %s is not set", option_utf8); | |
2137 g_free(option_utf8); | |
2138 return; | |
2139 } | |
2140 // Update the option | |
2141 // Maybe some options should be protected when user is connected (server, | |
2142 // username, etc.). And we should catch some options here, too | |
2143 // (hide_offline_buddies for ex.) | |
2144 if (!value) { | |
2145 settings_del(SETTINGS_TYPE_OPTION, option_utf8); | |
2146 } else { | |
2147 gchar *value_utf8 = to_utf8(value); | |
2148 settings_set(SETTINGS_TYPE_OPTION, option_utf8, value_utf8); | |
2149 g_free(value_utf8); | |
2150 g_free(value); | |
2151 } | |
2152 g_free(option_utf8); | |
2153 } | |
2154 | |
2155 static void dump_alias(char *k, char *v, void *param) | |
2156 { | |
2157 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, "Alias %s = %s", k, v); | |
2158 } | |
2159 | |
2160 static void do_alias(char *arg) | |
2161 { | |
2162 guint assign; | |
2163 gchar *alias, *value; | |
2164 | |
2165 assign = parse_assigment(arg, &alias, &value); | |
2166 if (!alias) { | |
2167 settings_foreach(SETTINGS_TYPE_ALIAS, &dump_alias, NULL); | |
2168 return; | |
2169 } | |
2170 if (!assign) { // This is a query | |
2171 const char *val = settings_get(SETTINGS_TYPE_ALIAS, alias); | |
2172 // NOTE: LPRINT_NOTUTF8 here, see below why it isn't encoded... | |
2173 if (val) | |
2174 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, "%s = %s", alias, val); | |
2175 else | |
2176 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
2177 "Alias '%s' does not exist", alias); | |
2178 goto do_alias_return; | |
2179 } | |
2180 // Check the alias does not conflict with a registered command | |
2181 if (cmd_get(alias)) { | |
2182 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
2183 "'%s' is a reserved word!", alias); | |
2184 goto do_alias_return; | |
2185 } | |
2186 // Update the alias | |
2187 if (!value) { | |
2188 if (settings_get(SETTINGS_TYPE_ALIAS, alias)) { | |
2189 settings_del(SETTINGS_TYPE_ALIAS, alias); | |
2190 // Remove alias from the completion list | |
2191 compl_del_category_word(COMPL_CMD, alias); | |
2192 } | |
2193 } else { | |
2194 /* Add alias to the completion list, if not already in. | |
2195 NOTE: We're not UTF8-encoding "alias" and "value" here because UTF-8 is | |
2196 not yet supported in the UI... (and we use the values in the completion | |
2197 system) | |
2198 */ | |
2199 if (!settings_get(SETTINGS_TYPE_ALIAS, alias)) | |
2200 compl_add_category_word(COMPL_CMD, alias); | |
2201 settings_set(SETTINGS_TYPE_ALIAS, alias, value); | |
2202 g_free(value); | |
2203 } | |
2204 do_alias_return: | |
2205 g_free(alias); | |
2206 } | |
2207 | |
2208 static void dump_bind(char *k, char *v, void *param) | |
2209 { | |
2210 scr_LogPrint(LPRINT_NORMAL, "Key %4s is bound to: %s", k, v); | |
2211 } | |
2212 | |
2213 static void do_bind(char *arg) | |
2214 { | |
2215 guint assign; | |
2216 gchar *k_code, *value; | |
2217 | |
2218 assign = parse_assigment(arg, &k_code, &value); | |
2219 if (!k_code) { | |
2220 settings_foreach(SETTINGS_TYPE_BINDING, &dump_bind, NULL); | |
2221 return; | |
2222 } | |
2223 if (!assign) { // This is a query | |
2224 const char *val = settings_get(SETTINGS_TYPE_BINDING, k_code); | |
2225 if (val) | |
2226 scr_LogPrint(LPRINT_NORMAL, "Key %s is bound to: %s", k_code, val); | |
2227 else | |
2228 scr_LogPrint(LPRINT_NORMAL, "Key %s is not bound.", k_code); | |
2229 g_free(k_code); | |
2230 return; | |
2231 } | |
2232 // Update the key binding | |
2233 if (!value) { | |
2234 settings_del(SETTINGS_TYPE_BINDING, k_code); | |
2235 } else { | |
2236 gchar *value_utf8 = to_utf8(value); | |
2237 settings_set(SETTINGS_TYPE_BINDING, k_code, value_utf8); | |
2238 g_free(value_utf8); | |
2239 g_free(value); | |
2240 } | |
2241 g_free(k_code); | |
2242 } | |
2243 | |
2244 static void do_rawxml(char *arg) | |
2245 { | |
2246 char **paramlst; | |
2247 char *subcmd; | |
2248 | |
2249 if (!lm_connection_is_authenticated(lconnection)) { | |
2250 scr_LogPrint(LPRINT_NORMAL, "You are not connected."); | |
2251 return; | |
2252 } | |
2253 | |
2254 paramlst = split_arg(arg, 2, 1); // subcmd, arg | |
2255 subcmd = *paramlst; | |
2256 arg = *(paramlst+1); | |
2257 | |
2258 if (!subcmd || !*subcmd) { | |
2259 scr_LogPrint(LPRINT_NORMAL, "Please read the manual page" | |
2260 " before using /rawxml :-)"); | |
2261 free_arg_lst(paramlst); | |
2262 return; | |
2263 } | |
2264 | |
2265 if (!strcasecmp(subcmd, "send")) { | |
2266 gchar *buffer; | |
2267 | |
2268 if (!subcmd || !*subcmd) { | |
2269 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
2270 free_arg_lst(paramlst); | |
2271 return; | |
2272 } | |
2273 | |
2274 // We don't strip_arg_special_chars() here, because it would be a pain for | |
2275 // the user to escape quotes in a XML stream... | |
2276 | |
2277 buffer = to_utf8(arg); | |
2278 if (buffer) { | |
2279 scr_LogPrint(LPRINT_NORMAL, "Sending XML string"); | |
2280 lm_connection_send_raw(lconnection, buffer, NULL); | |
2281 g_free(buffer); | |
2282 } else { | |
2283 scr_LogPrint(LPRINT_NORMAL, "Conversion error in XML string."); | |
2284 } | |
2285 } else { | |
2286 scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); | |
2287 } | |
2288 | |
2289 free_arg_lst(paramlst); | |
2290 } | |
2291 | |
2292 // check_room_subcommand(arg, param_needed, buddy_must_be_a_room) | |
2293 // - Check if this is a room, if buddy_must_be_a_room is not null | |
2294 // - Check there is at least 1 parameter, if param_needed is true | |
2295 // - Return null if one of the checks fails, or a pointer to the first | |
2296 // non-space character. | |
2297 static char *check_room_subcommand(char *arg, bool param_needed, | |
2298 gpointer buddy_must_be_a_room) | |
2299 { | |
2300 if (buddy_must_be_a_room && | |
2301 !(buddy_gettype(buddy_must_be_a_room) & ROSTER_TYPE_ROOM)) { | |
2302 scr_LogPrint(LPRINT_NORMAL, "This isn't a conference room."); | |
2303 return NULL; | |
2304 } | |
2305 | |
2306 if (param_needed) { | |
2307 if (!arg) { | |
2308 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
2309 return NULL; | |
2310 } | |
2311 } | |
2312 | |
2313 if (arg) | |
2314 return arg; | |
2315 else | |
2316 return ""; | |
2317 } | |
2318 | |
2319 static void room_join(gpointer bud, char *arg) | |
2320 { | |
2321 char **paramlst; | |
2322 char *roomname, *nick, *pass; | |
2323 char *roomname_tmp = NULL; | |
2324 char *pass_utf8; | |
2325 | |
2326 paramlst = split_arg(arg, 3, 0); // roomid, nickname, password | |
2327 roomname = *paramlst; | |
2328 nick = *(paramlst+1); | |
2329 pass = *(paramlst+2); | |
2330 | |
2331 if (!roomname) | |
2332 nick = NULL; | |
2333 if (!nick) | |
2334 pass = NULL; | |
2335 | |
2336 if (!roomname || !strcmp(roomname, ".")) { | |
2337 // If the current_buddy is recognized as a room, the room name | |
2338 // can be omitted (or "." can be used). | |
2339 if (!bud || !(buddy_gettype(bud) & ROSTER_TYPE_ROOM)) { | |
2340 scr_LogPrint(LPRINT_NORMAL, "Please specify a room name."); | |
2341 free_arg_lst(paramlst); | |
2342 return; | |
2343 } | |
2344 roomname = (char*)buddy_getjid(bud); | |
2345 } else if (strchr(roomname, '/')) { | |
2346 scr_LogPrint(LPRINT_NORMAL, "Invalid room name."); | |
2347 free_arg_lst(paramlst); | |
2348 return; | |
2349 } else { | |
2350 // The room id has been specified. Let's convert it and use it. | |
2351 mc_strtolower(roomname); | |
2352 roomname = roomname_tmp = to_utf8(roomname); | |
2353 } | |
2354 | |
2355 // If no nickname is provided with the /join command, | |
2356 // we try to get a default nickname. | |
2357 if (!nick || !*nick) | |
2358 nick = default_muc_nickname(roomname); | |
2359 else | |
2360 nick = to_utf8(nick); | |
2361 // If we still have no nickname, give up | |
2362 if (!nick || !*nick) { | |
2363 scr_LogPrint(LPRINT_NORMAL, "Please specify a nickname."); | |
2364 g_free(nick); | |
2365 free_arg_lst(paramlst); | |
2366 return; | |
2367 } | |
2368 | |
2369 pass_utf8 = to_utf8(pass); | |
2370 | |
2371 xmpp_room_join(roomname, nick, pass_utf8); | |
2372 | |
2373 scr_LogPrint(LPRINT_LOGNORM, "Sent a join request to <%s>...", roomname); | |
2374 | |
2375 g_free(roomname_tmp); | |
2376 g_free(nick); | |
2377 g_free(pass_utf8); | |
2378 buddylist_build(); | |
2379 update_roster = TRUE; | |
2380 free_arg_lst(paramlst); | |
2381 } | |
2382 | |
2383 static void room_invite(gpointer bud, char *arg) | |
2384 { | |
2385 char **paramlst; | |
2386 const gchar *roomname; | |
2387 char* fjid; | |
2388 gchar *reason_utf8; | |
2389 | |
2390 paramlst = split_arg(arg, 2, 1); // jid, [reason] | |
2391 fjid = *paramlst; | |
2392 arg = *(paramlst+1); | |
2393 // An empty reason is no reason... | |
2394 if (arg && !*arg) | |
2395 arg = NULL; | |
2396 | |
2397 if (!fjid || !*fjid) { | |
2398 scr_LogPrint(LPRINT_NORMAL, "Missing or incorrect Jabber ID."); | |
2399 free_arg_lst(paramlst); | |
2400 return; | |
2401 } | |
2402 | |
2403 roomname = buddy_getjid(bud); | |
2404 reason_utf8 = to_utf8(arg); | |
2405 xmpp_room_invite(roomname, fjid, reason_utf8); | |
2406 scr_LogPrint(LPRINT_LOGNORM, "Invitation sent to <%s>.", fjid); | |
2407 g_free(reason_utf8); | |
2408 free_arg_lst(paramlst); | |
2409 } | |
2410 | |
2411 static void room_affil(gpointer bud, char *arg) | |
2412 { | |
2413 char **paramlst; | |
2414 gchar *fjid, *rolename; | |
2415 struct role_affil ra; | |
2416 const char *roomid = buddy_getjid(bud); | |
2417 | |
2418 paramlst = split_arg(arg, 3, 1); // jid, new_affil, [reason] | |
2419 fjid = *paramlst; | |
2420 rolename = *(paramlst+1); | |
2421 arg = *(paramlst+2); | |
2422 | |
2423 if (!fjid || !*fjid || !rolename || !*rolename) { | |
2424 scr_LogPrint(LPRINT_NORMAL, "Please specify both a Jabber ID and a role."); | |
2425 free_arg_lst(paramlst); | |
2426 return; | |
2427 } | |
2428 | |
2429 ra.type = type_affil; | |
2430 ra.val.affil = affil_none; | |
2431 for (; ra.val.affil < imaffiliation_size; ra.val.affil++) | |
2432 if (!strcasecmp(rolename, straffil[ra.val.affil])) | |
2433 break; | |
2434 | |
2435 if (ra.val.affil < imaffiliation_size) { | |
2436 gchar *jid_utf8, *reason_utf8; | |
2437 jid_utf8 = to_utf8(fjid); | |
2438 reason_utf8 = to_utf8(arg); | |
2439 xmpp_room_setattrib(roomid, jid_utf8, NULL, ra, reason_utf8); | |
2440 g_free(jid_utf8); | |
2441 g_free(reason_utf8); | |
2442 } else | |
2443 scr_LogPrint(LPRINT_NORMAL, "Wrong affiliation parameter."); | |
2444 | |
2445 free_arg_lst(paramlst); | |
2446 } | |
2447 | |
2448 static void room_role(gpointer bud, char *arg) | |
2449 { | |
2450 char **paramlst; | |
2451 gchar *fjid, *rolename; | |
2452 struct role_affil ra; | |
2453 const char *roomid = buddy_getjid(bud); | |
2454 | |
2455 paramlst = split_arg(arg, 3, 1); // jid, new_role, [reason] | |
2456 fjid = *paramlst; | |
2457 rolename = *(paramlst+1); | |
2458 arg = *(paramlst+2); | |
2459 | |
2460 if (!fjid || !*fjid || !rolename || !*rolename) { | |
2461 scr_LogPrint(LPRINT_NORMAL, "Please specify both a Jabber ID and a role."); | |
2462 free_arg_lst(paramlst); | |
2463 return; | |
2464 } | |
2465 | |
2466 ra.type = type_role; | |
2467 ra.val.role = role_none; | |
2468 for (; ra.val.role < imrole_size; ra.val.role++) | |
2469 if (!strcasecmp(rolename, strrole[ra.val.role])) | |
2470 break; | |
2471 | |
2472 if (ra.val.role < imrole_size) { | |
2473 gchar *jid_utf8, *reason_utf8; | |
2474 jid_utf8 = to_utf8(fjid); | |
2475 reason_utf8 = to_utf8(arg); | |
2476 xmpp_room_setattrib(roomid, jid_utf8, NULL, ra, reason_utf8); | |
2477 g_free(jid_utf8); | |
2478 g_free(reason_utf8); | |
2479 } else | |
2480 scr_LogPrint(LPRINT_NORMAL, "Wrong role parameter."); | |
2481 | |
2482 free_arg_lst(paramlst); | |
2483 } | |
2484 | |
2485 | |
2486 // The expected argument is a Jabber id | |
2487 static void room_ban(gpointer bud, char *arg) | |
2488 { | |
2489 char **paramlst; | |
2490 gchar *fjid, *bjid; | |
2491 const gchar *banjid; | |
2492 gchar *jid_utf8, *reason_utf8; | |
2493 struct role_affil ra; | |
2494 const char *roomid = buddy_getjid(bud); | |
2495 | |
2496 paramlst = split_arg(arg, 2, 1); // jid, [reason] | |
2497 fjid = *paramlst; | |
2498 arg = *(paramlst+1); | |
2499 | |
2500 if (!fjid || !*fjid) { | |
2501 scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID."); | |
2502 free_arg_lst(paramlst); | |
2503 return; | |
2504 } | |
2505 | |
2506 ra.type = type_affil; | |
2507 ra.val.affil = affil_outcast; | |
2508 | |
2509 bjid = jidtodisp(fjid); | |
2510 jid_utf8 = to_utf8(bjid); | |
2511 | |
2512 // If the argument doesn't look like a jid, we'll try to find a matching | |
2513 // nickname. | |
2514 if (!strchr(bjid, JID_DOMAIN_SEPARATOR) || check_jid_syntax(bjid)) { | |
2515 const gchar *tmp; | |
2516 // We want the initial argument, so the fjid variable, because | |
2517 // we don't want to strip a resource-like string from the nickname! | |
2518 g_free(jid_utf8); | |
2519 jid_utf8 = to_utf8(fjid); | |
2520 tmp = buddy_getrjid(bud, jid_utf8); | |
2521 if (!tmp) { | |
2522 scr_LogPrint(LPRINT_NORMAL, "Wrong JID or nickname"); | |
2523 goto room_ban_return; | |
2524 } | |
2525 banjid = jidtodisp(tmp); | |
2526 } else | |
2527 banjid = jid_utf8; | |
2528 | |
2529 scr_LogPrint(LPRINT_NORMAL, "Requesting a ban for %s", banjid); | |
2530 | |
2531 reason_utf8 = to_utf8(arg); | |
2532 xmpp_room_setattrib(roomid, banjid, NULL, ra, reason_utf8); | |
2533 g_free(reason_utf8); | |
2534 | |
2535 room_ban_return: | |
2536 g_free(bjid); | |
2537 g_free(jid_utf8); | |
2538 free_arg_lst(paramlst); | |
2539 } | |
2540 | |
2541 // The expected argument is a Jabber id | |
2542 static void room_unban(gpointer bud, char *arg) | |
2543 { | |
2544 gchar *fjid = arg; | |
2545 gchar *jid_utf8; | |
2546 struct role_affil ra; | |
2547 const char *roomid = buddy_getjid(bud); | |
2548 | |
2549 if (!fjid || !*fjid) { | |
2550 scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID."); | |
2551 return; | |
2552 } | |
2553 | |
2554 ra.type = type_affil; | |
2555 ra.val.affil = affil_none; | |
2556 | |
2557 jid_utf8 = to_utf8(fjid); | |
2558 xmpp_room_setattrib(roomid, jid_utf8, NULL, ra, NULL); | |
2559 g_free(jid_utf8); | |
2560 } | |
2561 | |
2562 // The expected argument is a nickname | |
2563 static void room_kick(gpointer bud, char *arg) | |
2564 { | |
2565 char **paramlst; | |
2566 gchar *nick; | |
2567 gchar *nick_utf8, *reason_utf8; | |
2568 struct role_affil ra; | |
2569 const char *roomid = buddy_getjid(bud); | |
2570 | |
2571 paramlst = split_arg(arg, 2, 1); // nickname, [reason] | |
2572 nick = *paramlst; | |
2573 arg = *(paramlst+1); | |
2574 | |
2575 if (!nick || !*nick) { | |
2576 scr_LogPrint(LPRINT_NORMAL, "Please specify a nickname."); | |
2577 free_arg_lst(paramlst); | |
2578 return; | |
2579 } | |
2580 | |
2581 ra.type = type_role; | |
2582 ra.val.affil = role_none; | |
2583 | |
2584 nick_utf8 = to_utf8(nick); | |
2585 reason_utf8 = to_utf8(arg); | |
2586 xmpp_room_setattrib(roomid, NULL, nick_utf8, ra, reason_utf8); | |
2587 g_free(nick_utf8); | |
2588 g_free(reason_utf8); | |
2589 | |
2590 free_arg_lst(paramlst); | |
2591 } | |
2592 | |
2593 void cmd_room_leave(gpointer bud, char *arg) | |
2594 { | |
2595 gchar *roomid, *desc; | |
2596 const char *nickname; | |
2597 | |
2598 nickname = buddy_getnickname(bud); | |
2599 if (!nickname) { | |
2600 scr_LogPrint(LPRINT_NORMAL, "You are not in this room."); | |
2601 return; | |
2602 } | |
2603 | |
2604 roomid = g_strdup_printf("%s/%s", buddy_getjid(bud), nickname); | |
2605 desc = to_utf8(arg); | |
2606 xmpp_setstatus(offline, roomid, desc, TRUE); | |
2607 g_free(desc); | |
2608 g_free(roomid); | |
2609 } | |
2610 | |
2611 static void room_nick(gpointer bud, char *arg) | |
2612 { | |
2613 if (!buddy_getinsideroom(bud)) { | |
2614 scr_LogPrint(LPRINT_NORMAL, "You are not in this room."); | |
2615 return; | |
2616 } | |
2617 | |
2618 if (!arg || !*arg) { | |
2619 const char *nick = buddy_getnickname(bud); | |
2620 if (nick) | |
2621 scr_LogPrint(LPRINT_NORMAL, "Your nickname is: %s", nick); | |
2622 else | |
2623 scr_LogPrint(LPRINT_NORMAL, "You have no nickname in this room."); | |
2624 } else { | |
2625 gchar *nick = to_utf8(arg); | |
2626 strip_arg_special_chars(nick); | |
2627 xmpp_room_join(buddy_getjid(bud), nick, NULL); | |
2628 g_free(nick); | |
2629 } | |
2630 } | |
2631 | |
2632 static void room_privmsg(gpointer bud, char *arg) | |
2633 { | |
2634 char **paramlst; | |
2635 gchar *fjid_utf8, *nick, *nick_utf8, *msg; | |
2636 | |
2637 paramlst = split_arg(arg, 2, 1); // nickname, message | |
2638 nick = *paramlst; | |
2639 arg = *(paramlst+1); | |
2640 | |
2641 if (!nick || !*nick || !arg || !*arg) { | |
2642 scr_LogPrint(LPRINT_NORMAL, | |
2643 "Please specify both a Jabber ID and a message."); | |
2644 free_arg_lst(paramlst); | |
2645 return; | |
2646 } | |
2647 | |
2648 nick_utf8 = to_utf8(nick); | |
2649 fjid_utf8 = g_strdup_printf("%s/%s", buddy_getjid(bud), nick_utf8); | |
2650 g_free (nick_utf8); | |
2651 msg = to_utf8(arg); | |
2652 send_message_to(fjid_utf8, msg, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET, FALSE); | |
2653 g_free(fjid_utf8); | |
2654 g_free(msg); | |
2655 free_arg_lst(paramlst); | |
2656 } | |
2657 | |
2658 static void room_remove(gpointer bud, char *arg) | |
2659 { | |
2660 if (*arg) { | |
2661 scr_LogPrint(LPRINT_NORMAL, "This action does not require a parameter; " | |
2662 "the currently-selected room will be removed."); | |
2663 return; | |
2664 } | |
2665 | |
2666 // Quick check: if there are resources, we haven't left | |
2667 if (buddy_getinsideroom(bud)) { | |
2668 scr_LogPrint(LPRINT_NORMAL, "You haven't left this room!"); | |
2669 return; | |
2670 } | |
2671 // Delete the room | |
2672 roster_del_user(buddy_getjid(bud)); | |
2673 scr_UpdateBuddyWindow(); | |
2674 buddylist_build(); | |
2675 update_roster = TRUE; | |
2676 } | |
2677 | |
2678 static void room_topic(gpointer bud, char *arg) | |
2679 { | |
2680 if (!buddy_getinsideroom(bud)) { | |
2681 scr_LogPrint(LPRINT_NORMAL, "You are not in this room."); | |
2682 return; | |
2683 } | |
2684 | |
2685 // If no parameter is given, display the current topic | |
2686 if (!*arg) { | |
2687 const char *topic = buddy_gettopic(bud); | |
2688 if (topic) | |
2689 scr_LogPrint(LPRINT_NORMAL, "Topic: %s", topic); | |
2690 else | |
2691 scr_LogPrint(LPRINT_NORMAL, "No topic has been set."); | |
2692 return; | |
2693 } | |
2694 | |
2695 // If arg is "-", let's clear the topic | |
2696 if (!strcmp(arg, "-")) | |
2697 arg = NULL; | |
2698 | |
2699 arg = to_utf8(arg); | |
2700 // Set the topic | |
2701 xmpp_send_msg(buddy_getjid(bud), NULL, ROSTER_TYPE_ROOM, arg ? arg : "", | |
2702 FALSE, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET, NULL); | |
2703 g_free(arg); | |
2704 } | |
2705 | |
2706 static void room_destroy(gpointer bud, char *arg) | |
2707 { | |
2708 gchar *msg; | |
2709 | |
2710 if (arg && *arg) | |
2711 msg = to_utf8(arg); | |
2712 else | |
2713 msg = NULL; | |
2714 | |
2715 xmpp_room_destroy(buddy_getjid(bud), NULL, msg); | |
2716 g_free(msg); | |
2717 } | |
2718 | |
2719 static void room_unlock(gpointer bud, char *arg) | |
2720 { | |
2721 if (*arg) { | |
2722 scr_LogPrint(LPRINT_NORMAL, "Unknown parameter."); | |
2723 return; | |
2724 } | |
2725 | |
2726 xmpp_room_unlock(buddy_getjid(bud)); | |
2727 } | |
2728 | |
2729 static void room_setopt(gpointer bud, char *arg) | |
2730 { | |
2731 char **paramlst; | |
2732 char *param, *value; | |
2733 enum { opt_none = 0, opt_printstatus, opt_autowhois } option = 0; | |
2734 | |
2735 paramlst = split_arg(arg, 2, 1); // param, value | |
2736 param = *paramlst; | |
2737 value = *(paramlst+1); | |
2738 if (!param) { | |
2739 scr_LogPrint(LPRINT_NORMAL, "Please specify a room option."); | |
2740 free_arg_lst(paramlst); | |
2741 return; | |
2742 } | |
2743 | |
2744 if (!strcasecmp(param, "print_status")) | |
2745 option = opt_printstatus; | |
2746 else if (!strcasecmp(param, "auto_whois")) | |
2747 option = opt_autowhois; | |
2748 else { | |
2749 scr_LogPrint(LPRINT_NORMAL, "Wrong option!"); | |
2750 free_arg_lst(paramlst); | |
2751 return; | |
2752 } | |
2753 | |
2754 // If no value is given, display the current value | |
2755 if (!value) { | |
2756 const char *strval; | |
2757 if (option == opt_printstatus) | |
2758 strval = strprintstatus[buddy_getprintstatus(bud)]; | |
2759 else | |
2760 strval = strautowhois[buddy_getautowhois(bud)]; | |
2761 scr_LogPrint(LPRINT_NORMAL, "%s is set to: %s", param, strval); | |
2762 free_arg_lst(paramlst); | |
2763 return; | |
2764 } | |
2765 | |
2766 if (option == opt_printstatus) { | |
2767 enum room_printstatus eval; | |
2768 if (!strcasecmp(value, "none")) | |
2769 eval = status_none; | |
2770 else if (!strcasecmp(value, "in_and_out")) | |
2771 eval = status_in_and_out; | |
2772 else if (!strcasecmp(value, "all")) | |
2773 eval = status_all; | |
2774 else { | |
2775 eval = status_default; | |
2776 if (strcasecmp(value, "default") != 0) | |
2777 scr_LogPrint(LPRINT_NORMAL, "Unrecognized value, assuming default..."); | |
2778 } | |
2779 buddy_setprintstatus(bud, eval); | |
2780 } else if (option == opt_autowhois) { | |
2781 enum room_autowhois eval; | |
2782 if (!strcasecmp(value, "on")) | |
2783 eval = autowhois_on; | |
2784 else if (!strcasecmp(value, "off")) | |
2785 eval = autowhois_off; | |
2786 else { | |
2787 eval = autowhois_default; | |
2788 if (strcasecmp(value, "default") != 0) | |
2789 scr_LogPrint(LPRINT_NORMAL, "Unrecognized value, assuming default..."); | |
2790 } | |
2791 buddy_setautowhois(bud, eval); | |
2792 } | |
2793 | |
2794 free_arg_lst(paramlst); | |
2795 } | |
2796 | |
2797 // cmd_room_whois(..) | |
2798 // If interactive is TRUE, chatmode can be enabled. | |
2799 void cmd_room_whois(gpointer bud, char *arg, guint interactive) | |
2800 { | |
2801 char **paramlst; | |
2802 gchar *nick, *buffer; | |
2803 const char *bjid, *realjid; | |
2804 const char *rst_msg; | |
2805 gchar rprio; | |
2806 enum imstatus rstatus; | |
2807 enum imrole role; | |
2808 enum imaffiliation affil; | |
2809 time_t rst_time; | |
2810 guint msg_flag = HBB_PREFIX_INFO; | |
2811 | |
2812 paramlst = split_arg(arg, 1, 0); // nickname | |
2813 nick = *paramlst; | |
2814 | |
2815 if (!nick || !*nick) { | |
2816 scr_LogPrint(LPRINT_NORMAL, "Please specify a nickname."); | |
2817 free_arg_lst(paramlst); | |
2818 return; | |
2819 } | |
2820 | |
2821 nick = to_utf8(nick); | |
2822 | |
2823 if (interactive) { | |
2824 // Enter chat mode | |
2825 scr_set_chatmode(TRUE); | |
2826 scr_ShowBuddyWindow(); | |
2827 } else | |
2828 msg_flag |= HBB_PREFIX_NOFLAG; | |
2829 | |
2830 bjid = buddy_getjid(bud); | |
2831 rstatus = buddy_getstatus(bud, nick); | |
2832 | |
2833 if (rstatus == offline) { | |
2834 scr_LogPrint(LPRINT_NORMAL, "No such member: %s", nick); | |
2835 free_arg_lst(paramlst); | |
2836 g_free(nick); | |
2837 return; | |
2838 } | |
2839 | |
2840 rst_time = buddy_getstatustime(bud, nick); | |
2841 rprio = buddy_getresourceprio(bud, nick); | |
2842 rst_msg = buddy_getstatusmsg(bud, nick); | |
2843 if (!rst_msg) rst_msg = ""; | |
2844 | |
2845 role = buddy_getrole(bud, nick); | |
2846 affil = buddy_getaffil(bud, nick); | |
2847 realjid = buddy_getrjid(bud, nick); | |
2848 | |
2849 buffer = g_new(char, 4096); | |
2850 | |
2851 snprintf(buffer, 4095, "Whois [%s]", nick); | |
2852 scr_WriteIncomingMessage(bjid, buffer, 0, msg_flag, 0); | |
2853 snprintf(buffer, 4095, "Status : [%c] %s", imstatus2char[rstatus], | |
2854 rst_msg); | |
2855 scr_WriteIncomingMessage(bjid, buffer, 0, msg_flag | HBB_PREFIX_CONT, 0); | |
2856 | |
2857 if (rst_time) { | |
2858 char tbuf[128]; | |
2859 | |
2860 strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", localtime(&rst_time)); | |
2861 snprintf(buffer, 127, "Timestamp: %s", tbuf); | |
2862 scr_WriteIncomingMessage(bjid, buffer, 0, msg_flag | HBB_PREFIX_CONT, 0); | |
2863 } | |
2864 | |
2865 if (realjid) { | |
2866 snprintf(buffer, 4095, "JID : <%s>", realjid); | |
2867 scr_WriteIncomingMessage(bjid, buffer, 0, msg_flag | HBB_PREFIX_CONT, 0); | |
2868 } | |
2869 | |
2870 snprintf(buffer, 4095, "Role : %s", strrole[role]); | |
2871 scr_WriteIncomingMessage(bjid, buffer, 0, msg_flag | HBB_PREFIX_CONT, 0); | |
2872 snprintf(buffer, 4095, "Affiliat.: %s", straffil[affil]); | |
2873 scr_WriteIncomingMessage(bjid, buffer, 0, msg_flag | HBB_PREFIX_CONT, 0); | |
2874 snprintf(buffer, 4095, "Priority : %d", rprio); | |
2875 scr_WriteIncomingMessage(bjid, buffer, 0, msg_flag | HBB_PREFIX_CONT, 0); | |
2876 | |
2877 scr_WriteIncomingMessage(bjid, "End of WHOIS", 0, msg_flag, 0); | |
2878 | |
2879 g_free(buffer); | |
2880 g_free(nick); | |
2881 free_arg_lst(paramlst); | |
2882 } | |
2883 | |
2884 static void room_bookmark(gpointer bud, char *arg) | |
2885 { | |
2886 const char *roomid; | |
2887 const char *name = NULL, *nick = NULL; | |
2888 char *tmpnick = NULL; | |
2889 enum room_autowhois autowhois = 0; | |
2890 enum room_printstatus printstatus = 0; | |
2891 enum { bm_add = 0, bm_del = 1 } action = 0; | |
2892 int autojoin = 0; | |
2893 int nick_set = 0; | |
2894 | |
2895 if (arg && *arg) { | |
2896 // /room bookmark [add|del] [[+|-]autojoin] [-|nick] | |
2897 char **paramlst; | |
2898 char **pp; | |
2899 | |
2900 paramlst = split_arg(arg, 3, 0); // At most 3 parameters | |
2901 for (pp = paramlst; *pp; pp++) { | |
2902 if (!strcasecmp(*pp, "add")) | |
2903 action = bm_add; | |
2904 else if (!strcasecmp(*pp, "del")) | |
2905 action = bm_del; | |
2906 else if (!strcasecmp(*pp, "-autojoin")) | |
2907 autojoin = 0; | |
2908 else if (!strcasecmp(*pp, "+autojoin") || !strcasecmp(*pp, "autojoin")) | |
2909 autojoin = 1; | |
2910 else if (!strcmp(*pp, "-")) | |
2911 nick_set = 1; | |
2912 else { | |
2913 nick_set = 1; | |
2914 nick = tmpnick = to_utf8 (*pp); | |
2915 } | |
2916 } | |
2917 free_arg_lst(paramlst); | |
2918 } | |
2919 | |
2920 roomid = buddy_getjid(bud); | |
2921 | |
2922 if (action == bm_add) { | |
2923 name = buddy_getname(bud); | |
2924 if (!nick_set) | |
2925 nick = buddy_getnickname(bud); | |
2926 printstatus = buddy_getprintstatus(bud); | |
2927 autowhois = buddy_getautowhois(bud); | |
2928 } | |
2929 | |
2930 xmpp_set_storage_bookmark(roomid, name, nick, NULL, autojoin, | |
2931 printstatus, autowhois); | |
2932 g_free (tmpnick); | |
2933 } | |
2934 | |
2935 static void display_all_bookmarks(void) | |
2936 { | |
2937 GSList *bm, *bmp; | |
2938 GString *sbuf; | |
2939 struct bookmark *bm_elt; | |
2940 | |
2941 bm = xmpp_get_all_storage_bookmarks(); | |
2942 | |
2943 if (!bm) | |
2944 return; | |
2945 | |
2946 sbuf = g_string_new(""); | |
2947 | |
2948 scr_WriteIncomingMessage(NULL, "List of MUC bookmarks:", | |
2949 0, HBB_PREFIX_INFO, 0); | |
2950 | |
2951 for (bmp = bm; bmp; bmp = g_slist_next(bmp)) { | |
2952 bm_elt = bmp->data; | |
2953 g_string_printf(sbuf, "%c <%s>", | |
2954 (bm_elt->autojoin ? '*' : ' '), bm_elt->roomjid); | |
2955 if (bm_elt->nick) | |
2956 g_string_append_printf(sbuf, " (%s)", bm_elt->nick); | |
2957 if (bm_elt->name) | |
2958 g_string_append_printf(sbuf, " %s", bm_elt->name); | |
2959 g_free(bm_elt->roomjid); | |
2960 g_free(bm_elt->name); | |
2961 g_free(bm_elt->nick); | |
2962 g_free(bm_elt); | |
2963 scr_WriteIncomingMessage(NULL, sbuf->str, | |
2964 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0); | |
2965 } | |
2966 | |
2967 scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE); | |
2968 update_roster = TRUE; | |
2969 g_string_free(sbuf, TRUE); | |
2970 g_slist_free(bm); | |
2971 } | |
2972 | |
2973 #ifdef MODULES_ENABLE | |
2974 static gint module_list_comparator(gconstpointer arg1, gconstpointer arg2) | |
2975 { | |
2976 const loaded_module_t *module = arg1; | |
2977 const char *name = arg2; | |
2978 return g_strcmp0(module->name, name); | |
2979 } | |
2980 | |
2981 static void do_load(char *arg) | |
2982 { | |
2983 GModule *mod; | |
2984 GSList *lmod; | |
2985 char *mdir, *path; | |
2986 if (!arg || !*arg) { | |
2987 scr_LogPrint(LPRINT_LOGNORM, "Missing modulename."); | |
2988 return; | |
2989 } | |
2990 lmod = g_slist_find_custom(loaded_modules, arg, module_list_comparator); | |
2991 if (lmod) { | |
2992 scr_LogPrint(LPRINT_LOGNORM, "Module %s is already loaded.", arg); | |
2993 return; | |
2994 } | |
2995 mdir = expand_filename(settings_opt_get("modules_dir")); | |
2996 path = g_module_build_path(mdir, arg); | |
2997 mod = g_module_open(path, G_MODULE_BIND_LAZY); | |
2998 if (!mod) | |
2999 scr_LogPrint(LPRINT_LOGNORM, "Module loading failed: %s", | |
3000 g_module_error()); | |
3001 else { | |
3002 loaded_module_t *module = g_new(loaded_module_t, 1); | |
3003 module->name = g_strdup(arg); | |
3004 module->module = mod; | |
3005 loaded_modules = g_slist_prepend(loaded_modules, module); | |
3006 scr_LogPrint(LPRINT_LOGNORM, "Loaded module %s.", arg); | |
3007 } | |
3008 g_free(path); | |
3009 g_free(mdir); | |
3010 } | |
3011 | |
3012 static void do_unload(char *arg) | |
3013 { | |
3014 GSList *module; | |
3015 if (!arg || !*arg) { | |
3016 scr_LogPrint(LPRINT_LOGNORM, "Missing modulename."); | |
3017 return; | |
3018 } | |
3019 module = g_slist_find_custom(loaded_modules, arg, module_list_comparator); | |
3020 if (module) { | |
3021 loaded_module_t *mod = module->data; | |
3022 if (!g_module_close(mod->module)) | |
3023 scr_LogPrint(LPRINT_LOGNORM, "Module unloading failed: %s", | |
3024 g_module_error()); | |
3025 else { | |
3026 g_free(mod->name); | |
3027 g_free(mod); | |
3028 loaded_modules = g_slist_delete_link(loaded_modules, module); | |
3029 scr_LogPrint(LPRINT_LOGNORM, "Unloaded module %s.", arg); | |
3030 } | |
3031 } else | |
3032 scr_LogPrint(LPRINT_LOGNORM, "Module %s not loaded.", arg); | |
3033 } | |
3034 #endif | |
3035 | |
3036 static void do_room(char *arg) | |
3037 { | |
3038 char **paramlst; | |
3039 char *subcmd; | |
3040 gpointer bud; | |
3041 | |
3042 if (!lm_connection_is_authenticated(lconnection)) { | |
3043 scr_LogPrint(LPRINT_NORMAL, "You are not connected."); | |
3044 return; | |
3045 } | |
3046 | |
3047 paramlst = split_arg(arg, 2, 1); // subcmd, arg | |
3048 subcmd = *paramlst; | |
3049 arg = *(paramlst+1); | |
3050 | |
3051 if (!subcmd || !*subcmd) { | |
3052 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
3053 free_arg_lst(paramlst); | |
3054 return; | |
3055 } | |
3056 | |
3057 if (current_buddy) { | |
3058 bud = BUDDATA(current_buddy); | |
3059 } else { | |
3060 if (strcasecmp(subcmd, "join")) { | |
3061 free_arg_lst(paramlst); | |
3062 return; | |
3063 } | |
3064 // "room join" is a special case, we don't need to have a valid | |
3065 // current_buddy. | |
3066 bud = NULL; | |
3067 } | |
3068 | |
3069 if (!strcasecmp(subcmd, "join")) { | |
3070 if ((arg = check_room_subcommand(arg, FALSE, NULL)) != NULL) | |
3071 room_join(bud, arg); | |
3072 } else if (!strcasecmp(subcmd, "invite")) { | |
3073 if ((arg = check_room_subcommand(arg, TRUE, bud)) != NULL) | |
3074 room_invite(bud, arg); | |
3075 } else if (!strcasecmp(subcmd, "affil")) { | |
3076 if ((arg = check_room_subcommand(arg, TRUE, bud)) != NULL) | |
3077 room_affil(bud, arg); | |
3078 } else if (!strcasecmp(subcmd, "role")) { | |
3079 if ((arg = check_room_subcommand(arg, TRUE, bud)) != NULL) | |
3080 room_role(bud, arg); | |
3081 } else if (!strcasecmp(subcmd, "ban")) { | |
3082 if ((arg = check_room_subcommand(arg, TRUE, bud)) != NULL) | |
3083 room_ban(bud, arg); | |
3084 } else if (!strcasecmp(subcmd, "unban")) { | |
3085 if ((arg = check_room_subcommand(arg, TRUE, bud)) != NULL) | |
3086 room_unban(bud, arg); | |
3087 } else if (!strcasecmp(subcmd, "kick")) { | |
3088 if ((arg = check_room_subcommand(arg, TRUE, bud)) != NULL) | |
3089 room_kick(bud, arg); | |
3090 } else if (!strcasecmp(subcmd, "leave")) { | |
3091 if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL) | |
3092 cmd_room_leave(bud, arg); | |
3093 } else if (!strcasecmp(subcmd, "names")) { | |
3094 if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL) | |
3095 room_names(bud, arg); | |
3096 } else if (!strcasecmp(subcmd, "nick")) { | |
3097 if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL) | |
3098 room_nick(bud, arg); | |
3099 } else if (!strcasecmp(subcmd, "privmsg")) { | |
3100 if ((arg = check_room_subcommand(arg, TRUE, bud)) != NULL) | |
3101 room_privmsg(bud, arg); | |
3102 } else if (!strcasecmp(subcmd, "remove")) { | |
3103 if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL) | |
3104 room_remove(bud, arg); | |
3105 } else if (!strcasecmp(subcmd, "destroy")) { | |
3106 if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL) | |
3107 room_destroy(bud, arg); | |
3108 } else if (!strcasecmp(subcmd, "unlock")) { | |
3109 if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL) | |
3110 room_unlock(bud, arg); | |
3111 } else if (!strcasecmp(subcmd, "setopt")) { | |
3112 if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL) | |
3113 room_setopt(bud, arg); | |
3114 } else if (!strcasecmp(subcmd, "topic")) { | |
3115 if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL) | |
3116 room_topic(bud, arg); | |
3117 } else if (!strcasecmp(subcmd, "whois")) { | |
3118 if ((arg = check_room_subcommand(arg, TRUE, bud)) != NULL) | |
3119 cmd_room_whois(bud, arg, TRUE); | |
3120 } else if (!strcasecmp(subcmd, "bookmark")) { | |
3121 if (!arg && !buddy_getjid(BUDDATA(current_buddy)) && | |
3122 buddy_gettype(BUDDATA(current_buddy)) == ROSTER_TYPE_SPECIAL) | |
3123 display_all_bookmarks(); | |
3124 else if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL) | |
3125 room_bookmark(bud, arg); | |
3126 } else { | |
3127 scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); | |
3128 } | |
3129 | |
3130 free_arg_lst(paramlst); | |
3131 } | |
3132 | |
3133 static void do_authorization(char *arg) | |
3134 { | |
3135 char **paramlst; | |
3136 char *subcmd; | |
3137 char *jid_utf8; | |
3138 | |
3139 if (!lm_connection_is_authenticated(lconnection)) { | |
3140 scr_LogPrint(LPRINT_NORMAL, "You are not connected."); | |
3141 return; | |
3142 } | |
3143 | |
3144 paramlst = split_arg(arg, 2, 0); // subcmd, [jid] | |
3145 subcmd = *paramlst; | |
3146 arg = *(paramlst+1); | |
3147 | |
3148 if (!subcmd || !*subcmd) { | |
3149 scr_LogPrint(LPRINT_NORMAL, "Missing parameter."); | |
3150 goto do_authorization_return; | |
3151 } | |
3152 | |
3153 // Use the provided jid, if it looks valid | |
3154 if (arg) { | |
3155 if (!*arg) { | |
3156 // If no jid is provided, we use the current selected buddy | |
3157 arg = NULL; | |
3158 } else { | |
3159 if (check_jid_syntax(arg)) { | |
3160 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
3161 "<%s> is not a valid Jabber ID.", arg); | |
3162 goto do_authorization_return; | |
3163 } | |
3164 } | |
3165 } | |
3166 | |
3167 if (!arg) { // Use the current selected buddy's jid | |
3168 gpointer bud; | |
3169 guint type; | |
3170 | |
3171 if (!current_buddy) | |
3172 goto do_authorization_return; | |
3173 bud = BUDDATA(current_buddy); | |
3174 | |
3175 jid_utf8 = arg = (char*)buddy_getjid(bud); | |
3176 type = buddy_gettype(bud); | |
3177 | |
3178 if (!(type & (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT))) { | |
3179 scr_LogPrint(LPRINT_NORMAL, "Invalid buddy."); | |
3180 goto do_authorization_return; | |
3181 } | |
3182 } else { | |
3183 jid_utf8 = to_utf8(arg); | |
3184 } | |
3185 | |
3186 if (!strcasecmp(subcmd, "allow")) { | |
3187 xmpp_send_s10n(jid_utf8, LM_MESSAGE_SUB_TYPE_SUBSCRIBED); | |
3188 scr_LogPrint(LPRINT_LOGNORM, | |
3189 "Sent presence subscription approval to <%s>.", | |
3190 jid_utf8); | |
3191 } else if (!strcasecmp(subcmd, "cancel")) { | |
3192 xmpp_send_s10n(jid_utf8, LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED); | |
3193 scr_LogPrint(LPRINT_LOGNORM, | |
3194 "<%s> will no longer receive your presence updates.", | |
3195 jid_utf8); | |
3196 } else if (!strcasecmp(subcmd, "request")) { | |
3197 xmpp_send_s10n(jid_utf8, LM_MESSAGE_SUB_TYPE_SUBSCRIBE); | |
3198 scr_LogPrint(LPRINT_LOGNORM, | |
3199 "Sent presence notification request to <%s>.", jid_utf8); | |
3200 } else if (!strcasecmp(subcmd, "request_unsubscribe")) { | |
3201 xmpp_send_s10n(jid_utf8, LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE); | |
3202 scr_LogPrint(LPRINT_LOGNORM, | |
3203 "Sent presence notification unsubscription request to <%s>.", | |
3204 jid_utf8); | |
3205 } else { | |
3206 scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); | |
3207 } | |
3208 | |
3209 // Only free jid_utf8 if it has been allocated, i.e. if != arg. | |
3210 if (jid_utf8 && jid_utf8 != arg) | |
3211 g_free(jid_utf8); | |
3212 do_authorization_return: | |
3213 free_arg_lst(paramlst); | |
3214 } | |
3215 | |
3216 static void do_version(char *arg) | |
3217 { | |
3218 gchar *ver = mcabber_version(); | |
3219 scr_LogPrint(LPRINT_NORMAL, "This is mcabber version %s.", ver); | |
3220 g_free(ver); | |
3221 } | |
3222 | |
3223 static void do_request(char *arg) | |
3224 { | |
3225 char **paramlst; | |
3226 char *fjid, *type; | |
3227 enum iqreq_type numtype = iqreq_none; | |
3228 char *jid_utf8 = NULL; | |
3229 | |
3230 paramlst = split_arg(arg, 2, 0); // type, jid | |
3231 type = *paramlst; | |
3232 fjid = *(paramlst+1); | |
3233 | |
3234 if (type) { | |
3235 // Quick check... | |
3236 if (!strcasecmp(type, "version")) | |
3237 numtype = iqreq_version; | |
3238 else if (!strcasecmp(type, "time")) | |
3239 numtype = iqreq_time; | |
3240 else if (!strcasecmp(type, "last")) | |
3241 numtype = iqreq_last; | |
3242 else if (!strcasecmp(type, "vcard")) | |
3243 numtype = iqreq_vcard; | |
3244 } | |
3245 | |
3246 if (!type || !numtype) { | |
3247 scr_LogPrint(LPRINT_NORMAL, | |
3248 "Please specify a query type (version, time...)."); | |
3249 free_arg_lst(paramlst); | |
3250 return; | |
3251 } | |
3252 | |
3253 if (!lm_connection_is_authenticated(lconnection)) { | |
3254 scr_LogPrint(LPRINT_NORMAL, "You are not connected."); | |
3255 free_arg_lst(paramlst); | |
3256 return; | |
3257 } | |
3258 | |
3259 // Allow special jid "" or "." (current buddy) | |
3260 if (fjid && (!*fjid || !strcmp(fjid, "."))) | |
3261 fjid = NULL; | |
3262 | |
3263 if (fjid) { | |
3264 // The JID has been specified. Quick check... | |
3265 if (check_jid_syntax(fjid)) { | |
3266 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
3267 "<%s> is not a valid Jabber ID.", fjid); | |
3268 fjid = NULL; | |
3269 } else { | |
3270 // Convert jid to lowercase | |
3271 char *p; | |
3272 for (p = fjid; *p && *p != JID_RESOURCE_SEPARATOR; p++) | |
3273 *p = tolower(*p); | |
3274 fjid = jid_utf8 = to_utf8(fjid); | |
3275 } | |
3276 } else { | |
3277 // Add the current buddy | |
3278 if (current_buddy) | |
3279 fjid = (char*)buddy_getjid(BUDDATA(current_buddy)); | |
3280 if (!fjid) | |
3281 scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID."); | |
3282 } | |
3283 | |
3284 if (fjid) { | |
3285 switch (numtype) { | |
3286 case iqreq_version: | |
3287 case iqreq_time: | |
3288 case iqreq_last: | |
3289 case iqreq_vcard: | |
3290 xmpp_request(fjid, numtype); | |
3291 break; | |
3292 default: | |
3293 break; | |
3294 } | |
3295 } | |
3296 g_free(jid_utf8); | |
3297 free_arg_lst(paramlst); | |
3298 } | |
3299 | |
3300 static void do_event(char *arg) | |
3301 { | |
3302 char **paramlst; | |
3303 char *evid, *subcmd; | |
3304 int action = -1; | |
3305 GSList *evidlst; | |
3306 | |
3307 paramlst = split_arg(arg, 2, 0); // id, subcmd | |
3308 evid = *paramlst; | |
3309 subcmd = *(paramlst+1); | |
3310 | |
3311 if (!evid || !subcmd) { | |
3312 // Special case: /event list | |
3313 if (evid && !strcasecmp(evid, "list")) | |
3314 evs_display_list(); | |
3315 else | |
3316 scr_LogPrint(LPRINT_NORMAL, | |
3317 "Missing parameter. Usage: /event num action"); | |
3318 free_arg_lst(paramlst); | |
3319 return; | |
3320 } | |
3321 | |
3322 if (!strcasecmp(subcmd, "reject")) | |
3323 action = 0; | |
3324 else if (!strcasecmp(subcmd, "accept")) | |
3325 action = 1; | |
3326 else if (!strcasecmp(subcmd, "ignore")) | |
3327 action = 2; | |
3328 | |
3329 if (action == -1) { | |
3330 scr_LogPrint(LPRINT_NORMAL, "Wrong action parameter."); | |
3331 } else if (action >= 0 && action <= 2) { | |
3332 GSList *p; | |
3333 | |
3334 if (action == 2) { | |
3335 action = EVS_CONTEXT_CANCEL; | |
3336 } else { | |
3337 action += EVS_CONTEXT_USER; | |
3338 } | |
3339 | |
3340 if (!strcmp(evid, "*")) { | |
3341 // Use completion list | |
3342 evidlst = evs_geteventslist(FALSE); | |
3343 } else { | |
3344 // Let's create a slist with the provided event id | |
3345 evidlst = g_slist_append(NULL, g_strdup(evid)); | |
3346 } | |
3347 for (p = evidlst; p; p = g_slist_next(p)) { | |
3348 if (evs_callback(p->data, action) == -1) { | |
3349 scr_LogPrint(LPRINT_NORMAL, "Event %s not found.", p->data); | |
3350 } | |
3351 g_free(p->data); | |
3352 } | |
3353 g_slist_free(evidlst); | |
3354 } | |
3355 | |
3356 free_arg_lst(paramlst); | |
3357 } | |
3358 | |
3359 static void do_pgp(char *arg) | |
3360 { | |
3361 char **paramlst; | |
3362 char *fjid, *subcmd, *keyid; | |
3363 enum { | |
3364 pgp_none, | |
3365 pgp_enable, | |
3366 pgp_disable, | |
3367 pgp_setkey, | |
3368 pgp_force, | |
3369 pgp_info | |
3370 } op = 0; | |
3371 int force = FALSE; | |
3372 | |
3373 paramlst = split_arg(arg, 3, 0); // subcmd, jid, [key] | |
3374 subcmd = *paramlst; | |
3375 fjid = *(paramlst+1); | |
3376 keyid = *(paramlst+2); | |
3377 | |
3378 if (!subcmd) | |
3379 fjid = NULL; | |
3380 if (!fjid) | |
3381 keyid = NULL; | |
3382 | |
3383 if (subcmd) { | |
3384 if (!strcasecmp(subcmd, "enable")) | |
3385 op = pgp_enable; | |
3386 else if (!strcasecmp(subcmd, "disable")) | |
3387 op = pgp_disable; | |
3388 else if (!strcasecmp(subcmd, "setkey")) | |
3389 op = pgp_setkey; | |
3390 else if ((!strcasecmp(subcmd, "force")) || | |
3391 (!strcasecmp(subcmd, "+force"))) { | |
3392 op = pgp_force; | |
3393 force = TRUE; | |
3394 } else if (!strcasecmp(subcmd, "-force")) | |
3395 op = pgp_force; | |
3396 else if (!strcasecmp(subcmd, "info")) | |
3397 op = pgp_info; | |
3398 } | |
3399 | |
3400 if (!op) { | |
3401 scr_LogPrint(LPRINT_NORMAL, "Unrecognized or missing parameter!"); | |
3402 free_arg_lst(paramlst); | |
3403 return; | |
3404 } | |
3405 | |
3406 // Allow special jid "" or "." (current buddy) | |
3407 if (fjid && (!*fjid || !strcmp(fjid, "."))) | |
3408 fjid = NULL; | |
3409 | |
3410 if (fjid) { | |
3411 // The JID has been specified. Quick check... | |
3412 if (check_jid_syntax(fjid) || !strchr(fjid, '@')) { | |
3413 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
3414 "<%s> is not a valid Jabber ID.", fjid); | |
3415 fjid = NULL; | |
3416 } else { | |
3417 // Convert jid to lowercase and strip resource | |
3418 char *p; | |
3419 for (p = fjid; *p && *p != JID_RESOURCE_SEPARATOR; p++) | |
3420 *p = tolower(*p); | |
3421 if (*p == JID_RESOURCE_SEPARATOR) | |
3422 *p = '\0'; | |
3423 } | |
3424 } else { | |
3425 gpointer bud = NULL; | |
3426 if (current_buddy) | |
3427 bud = BUDDATA(current_buddy); | |
3428 if (bud) { | |
3429 guint type = buddy_gettype(bud); | |
3430 if (type & ROSTER_TYPE_USER) // Is it a user? | |
3431 fjid = (char*)buddy_getjid(bud); | |
3432 else | |
3433 scr_LogPrint(LPRINT_NORMAL, "The selected item should be a user."); | |
3434 } | |
3435 } | |
3436 | |
3437 if (fjid) { // fjid is actually a bare jid... | |
3438 guint disabled; | |
3439 GString *sbuf; | |
3440 switch (op) { | |
3441 case pgp_enable: | |
3442 case pgp_disable: | |
3443 settings_pgp_setdisabled(fjid, (op == pgp_disable ? TRUE : FALSE)); | |
3444 break; | |
3445 case pgp_force: | |
3446 settings_pgp_setforce(fjid, force); | |
3447 break; | |
3448 case pgp_setkey: | |
3449 settings_pgp_setkeyid(fjid, keyid); | |
3450 break; | |
3451 case pgp_info: | |
3452 sbuf = g_string_new(""); | |
3453 if (settings_pgp_getkeyid(fjid)) { | |
3454 g_string_printf(sbuf, "PGP Encryption key id: %s", | |
3455 settings_pgp_getkeyid(fjid)); | |
3456 scr_WriteIncomingMessage(fjid, sbuf->str, 0, HBB_PREFIX_INFO, 0); | |
3457 } | |
3458 disabled = settings_pgp_getdisabled(fjid); | |
3459 g_string_printf(sbuf, "PGP encryption is %s", | |
3460 (disabled ? "disabled" : "enabled")); | |
3461 scr_WriteIncomingMessage(fjid, sbuf->str, 0, HBB_PREFIX_INFO, 0); | |
3462 if (!disabled && settings_pgp_getforce(fjid)) { | |
3463 scr_WriteIncomingMessage(fjid, | |
3464 "Encryption enforced (no negotiation)", | |
3465 0, HBB_PREFIX_INFO, 0); | |
3466 } | |
3467 g_string_free(sbuf, TRUE); | |
3468 break; | |
3469 default: | |
3470 break; | |
3471 } | |
3472 } else { | |
3473 scr_LogPrint(LPRINT_NORMAL, "Please specify a valid Jabber ID."); | |
3474 } | |
3475 | |
3476 free_arg_lst(paramlst); | |
3477 } | |
3478 | |
3479 static void do_otr(char *arg) | |
3480 { | |
3481 #ifdef HAVE_LIBOTR | |
3482 char **paramlst; | |
3483 char *fjid, *subcmd, *keyid; | |
3484 enum { | |
3485 otr_none, | |
3486 otr_start, | |
3487 otr_stop, | |
3488 otr_fpr, | |
3489 otr_smpq, | |
3490 otr_smpr, | |
3491 otr_smpa, | |
3492 otr_k, | |
3493 otr_info | |
3494 } op = 0; | |
3495 | |
3496 if (!otr_enabled()) { | |
3497 scr_LogPrint(LPRINT_LOGNORM, | |
3498 "Warning: OTR hasn't been enabled -- command ignored."); | |
3499 return; | |
3500 } | |
3501 | |
3502 paramlst = split_arg(arg, 3, 0); // subcmd, jid, [key] | |
3503 subcmd = *paramlst; | |
3504 fjid = *(paramlst+1); | |
3505 keyid = *(paramlst+2); | |
3506 | |
3507 if (!subcmd) | |
3508 fjid = NULL; | |
3509 if (!fjid) | |
3510 keyid = NULL; | |
3511 | |
3512 if (subcmd) { | |
3513 if (!strcasecmp(subcmd, "start")) | |
3514 op = otr_start; | |
3515 else if (!strcasecmp(subcmd, "stop")) | |
3516 op = otr_stop; | |
3517 else if (!strcasecmp(subcmd, "fingerprint")) | |
3518 op = otr_fpr; | |
3519 else if (!strcasecmp(subcmd, "smpq")) | |
3520 op = otr_smpq; | |
3521 else if (!strcasecmp(subcmd, "smpr")) | |
3522 op = otr_smpr; | |
3523 else if (!strcasecmp(subcmd, "smpa")) | |
3524 op = otr_smpa; | |
3525 else if (!strcasecmp(subcmd, "key")) | |
3526 op = otr_k; | |
3527 else if (!strcasecmp(subcmd, "info")) | |
3528 op = otr_info; | |
3529 } | |
3530 | |
3531 if (!op) { | |
3532 scr_LogPrint(LPRINT_NORMAL, "Unrecognized or missing parameter!"); | |
3533 free_arg_lst(paramlst); | |
3534 return; | |
3535 } | |
3536 | |
3537 if (op == otr_k) | |
3538 otr_key(); | |
3539 else { | |
3540 // Allow special jid "" or "." (current buddy) | |
3541 if (fjid && (!*fjid || !strcmp(fjid, "."))) | |
3542 fjid = NULL; | |
3543 | |
3544 if (fjid) { | |
3545 // The JID has been specified. Quick check... | |
3546 if (check_jid_syntax(fjid) || !strchr(fjid, '@')) { | |
3547 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
3548 "<%s> is not a valid Jabber ID.", fjid); | |
3549 fjid = NULL; | |
3550 } else { | |
3551 // Convert jid to lowercase and strip resource | |
3552 char *p; | |
3553 for (p = fjid; *p && *p != JID_RESOURCE_SEPARATOR; p++) | |
3554 *p = tolower(*p); | |
3555 if (*p == JID_RESOURCE_SEPARATOR) | |
3556 *p = '\0'; | |
3557 } | |
3558 } else { | |
3559 gpointer bud = NULL; | |
3560 if (current_buddy) | |
3561 bud = BUDDATA(current_buddy); | |
3562 if (bud) { | |
3563 guint type = buddy_gettype(bud); | |
3564 if (type & ROSTER_TYPE_USER) // Is it a user? | |
3565 fjid = (char*)buddy_getjid(bud); | |
3566 else | |
3567 scr_LogPrint(LPRINT_NORMAL, "The selected item should be a user."); | |
3568 } | |
3569 } | |
3570 | |
3571 if (fjid) { // fjid is actually a bare jid... | |
3572 switch (op) { | |
3573 case otr_start: | |
3574 otr_establish(fjid); break; | |
3575 case otr_stop: | |
3576 otr_disconnect(fjid); break; | |
3577 case otr_fpr: | |
3578 otr_fingerprint(fjid, keyid); break; | |
3579 case otr_smpq: | |
3580 otr_smp_query(fjid, keyid); break; | |
3581 case otr_smpr: | |
3582 otr_smp_respond(fjid, keyid); break; | |
3583 case otr_smpa: | |
3584 otr_smp_abort(fjid); break; | |
3585 case otr_info: | |
3586 otr_print_info(fjid); break; | |
3587 default: | |
3588 break; | |
3589 } | |
3590 } else | |
3591 scr_LogPrint(LPRINT_NORMAL, "Please specify a valid Jabber ID."); | |
3592 } | |
3593 free_arg_lst(paramlst); | |
3594 | |
3595 #else | |
3596 scr_LogPrint(LPRINT_NORMAL, "Please recompile mcabber with libotr enabled."); | |
3597 #endif /* HAVE_LIBOTR */ | |
3598 } | |
3599 | |
3600 #ifdef HAVE_LIBOTR | |
3601 static char *string_for_otrpolicy(enum otr_policy p) | |
3602 { | |
3603 switch (p) { | |
3604 case plain: return "plain"; | |
3605 case opportunistic: return "opportunistic"; | |
3606 case manual: return "manual"; | |
3607 case always: return "always"; | |
3608 default: return "unknown"; | |
3609 } | |
3610 } | |
3611 | |
3612 static void dump_otrpolicy(char *k, char *v, void *nothing) | |
3613 { | |
3614 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, "otrpolicy for %s: %s", k, | |
3615 string_for_otrpolicy(*(enum otr_policy*)v)); | |
3616 } | |
3617 #endif | |
3618 | |
3619 static void do_otrpolicy(char *arg) | |
3620 { | |
3621 #ifdef HAVE_LIBOTR | |
3622 char **paramlst; | |
3623 char *fjid, *policy; | |
3624 enum otr_policy p; | |
3625 | |
3626 paramlst = split_arg(arg, 2, 0); // [jid|default] policy | |
3627 fjid = *paramlst; | |
3628 policy = *(paramlst+1); | |
3629 | |
3630 if (!fjid && !policy) { | |
3631 scr_LogPrint(LPRINT_NORMAL, "default otrpolicy: %s", | |
3632 string_for_otrpolicy(settings_otr_getpolicy(NULL))); | |
3633 settings_foreach(SETTINGS_TYPE_OTR, &dump_otrpolicy, NULL); | |
3634 free_arg_lst(paramlst); | |
3635 return; | |
3636 } | |
3637 | |
3638 if (!policy) { | |
3639 scr_LogPrint(LPRINT_NORMAL, | |
3640 "Please call otrpolicy correctly: /otrpolicy (default|jid) " | |
3641 "(plain|manual|opportunistic|always)"); | |
3642 free_arg_lst(paramlst); | |
3643 return; | |
3644 } | |
3645 | |
3646 if (!strcasecmp(policy, "plain")) | |
3647 p = plain; | |
3648 else if (!strcasecmp(policy, "manual")) | |
3649 p = manual; | |
3650 else if (!strcasecmp(policy, "opportunistic")) | |
3651 p = opportunistic; | |
3652 else if (!strcasecmp(policy, "always")) | |
3653 p = always; | |
3654 else { | |
3655 /* Fail, we don't know _this_ policy*/ | |
3656 scr_LogPrint(LPRINT_NORMAL, "mcabber doesn't support _this_ policy!"); | |
3657 free_arg_lst(paramlst); | |
3658 return; | |
3659 } | |
3660 | |
3661 if (!strcasecmp(fjid, "default") || !strcasecmp(fjid, "*")) { | |
3662 /*set default policy*/ | |
3663 settings_otr_setpolicy(NULL, p); | |
3664 free_arg_lst(paramlst); | |
3665 return; | |
3666 } | |
3667 // Allow special jid "" or "." (current buddy) | |
3668 if (fjid && (!*fjid || !strcmp(fjid, "."))) | |
3669 fjid = NULL; | |
3670 | |
3671 if (fjid) { | |
3672 // The JID has been specified. Quick check... | |
3673 if (check_jid_syntax(fjid) || !strchr(fjid, '@')) { | |
3674 scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8, | |
3675 "<%s> is not a valid Jabber ID.", fjid); | |
3676 fjid = NULL; | |
3677 } else { | |
3678 // Convert jid to lowercase and strip resource | |
3679 char *p; | |
3680 for (p = fjid; *p && *p != JID_RESOURCE_SEPARATOR; p++) | |
3681 *p = tolower(*p); | |
3682 if (*p == JID_RESOURCE_SEPARATOR) | |
3683 *p = '\0'; | |
3684 } | |
3685 } else { | |
3686 gpointer bud = NULL; | |
3687 if (current_buddy) | |
3688 bud = BUDDATA(current_buddy); | |
3689 if (bud) { | |
3690 guint type = buddy_gettype(bud); | |
3691 if (type & ROSTER_TYPE_USER) // Is it a user? | |
3692 fjid = (char*)buddy_getjid(bud); | |
3693 else | |
3694 scr_LogPrint(LPRINT_NORMAL, "The selected item should be a user."); | |
3695 } | |
3696 } | |
3697 | |
3698 if (fjid) | |
3699 settings_otr_setpolicy(fjid, p); | |
3700 else | |
3701 scr_LogPrint(LPRINT_NORMAL, "Please specify a valid Jabber ID."); | |
3702 | |
3703 free_arg_lst(paramlst); | |
3704 #else | |
3705 scr_LogPrint(LPRINT_NORMAL, "Please recompile mcabber with libotr enabled."); | |
3706 #endif /* HAVE_LIBOTR */ | |
3707 } | |
3708 | |
3709 /* !!! | |
3710 After changing the /iline arguments names here, you must change ones | |
3711 in init_bindings(). | |
3712 */ | |
3713 static void do_iline(char *arg) | |
3714 { | |
3715 if (!strcasecmp(arg, "fword")) { | |
3716 readline_forward_word(); | |
3717 } else if (!strcasecmp(arg, "bword")) { | |
3718 readline_backward_word(); | |
3719 } else if (!strcasecmp(arg, "word_fdel")) { | |
3720 readline_forward_kill_word(); | |
3721 } else if (!strcasecmp(arg, "word_bdel")) { | |
3722 readline_backward_kill_word(); | |
3723 } else if (!strcasecmp(arg, "word_upcase")) { | |
3724 readline_updowncase_word(1); | |
3725 } else if (!strcasecmp(arg, "word_downcase")) { | |
3726 readline_updowncase_word(0); | |
3727 } else if (!strcasecmp(arg, "word_capit")) { | |
3728 readline_capitalize_word(); | |
3729 } else if (!strcasecmp(arg, "fchar")) { | |
3730 readline_forward_char(); | |
3731 } else if (!strcasecmp(arg, "bchar")) { | |
3732 readline_backward_char(); | |
3733 } else if (!strcasecmp(arg, "char_fdel")) { | |
3734 readline_forward_kill_char(); | |
3735 } else if (!strcasecmp(arg, "char_bdel")) { | |
3736 readline_backward_kill_char(); | |
3737 } else if (!strcasecmp(arg, "char_swap")) { | |
3738 readline_transpose_chars(); | |
3739 } else if (!strcasecmp(arg, "hist_beginning_search_bwd")) { | |
3740 readline_hist_beginning_search_bwd(); | |
3741 } else if (!strcasecmp(arg, "hist_beginning_search_fwd")) { | |
3742 readline_hist_beginning_search_fwd(); | |
3743 } else if (!strcasecmp(arg, "hist_prev")) { | |
3744 readline_hist_prev(); | |
3745 } else if (!strcasecmp(arg, "hist_next")) { | |
3746 readline_hist_next(); | |
3747 } else if (!strcasecmp(arg, "iline_start")) { | |
3748 readline_iline_start(); | |
3749 } else if (!strcasecmp(arg, "iline_end")) { | |
3750 readline_iline_end(); | |
3751 } else if (!strcasecmp(arg, "iline_fdel")) { | |
3752 readline_forward_kill_iline(); | |
3753 } else if (!strcasecmp(arg, "iline_bdel")) { | |
3754 readline_backward_kill_iline(); | |
3755 } else if (!strcasecmp(arg, "send_multiline")) { | |
3756 readline_send_multiline(); | |
3757 } else if (!strcasecmp(arg, "iline_accept")) { | |
3758 retval_for_cmds = readline_accept_line(FALSE); | |
3759 } else if (!strcasecmp(arg, "iline_accept_down_hist")) { | |
3760 retval_for_cmds = readline_accept_line(TRUE); | |
3761 } else if (!strcasecmp(arg, "compl_cancel")) { | |
3762 readline_cancel_completion(); | |
3763 } else if (!strcasecmp(arg, "compl_do")) { | |
3764 readline_do_completion(); | |
3765 } | |
3766 } | |
3767 | |
3768 static void do_screen_refresh(char *arg) | |
3769 { | |
3770 readline_refresh_screen(); | |
3771 } | |
3772 | |
3773 static void do_chat_disable(char *arg) | |
3774 { | |
3775 guint show_roster; | |
3776 | |
3777 if (arg && !strcasecmp(arg, "--show-roster")) | |
3778 show_roster = 1; | |
3779 else | |
3780 show_roster = 0; | |
3781 | |
3782 readline_disable_chat_mode(show_roster); | |
3783 } | |
3784 | |
3785 static void do_source(char *arg) | |
3786 { | |
3787 static int recur_level; | |
3788 gchar *filename, *expfname; | |
3789 if (!*arg) { | |
3790 scr_LogPrint(LPRINT_NORMAL, "Missing filename."); | |
3791 return; | |
3792 } | |
3793 if (recur_level > 20) { | |
3794 scr_LogPrint(LPRINT_LOGNORM, "** Too many source commands!"); | |
3795 return; | |
3796 } | |
3797 filename = g_strdup(arg); | |
3798 strip_arg_special_chars(filename); | |
3799 expfname = expand_filename(filename); | |
3800 recur_level++; | |
3801 cfg_read_file(expfname, FALSE); | |
3802 recur_level--; | |
3803 g_free(filename); | |
3804 g_free(expfname); | |
3805 } | |
3806 | |
3807 static void do_connect(char *arg) | |
3808 { | |
3809 xmpp_connect(); | |
3810 } | |
3811 | |
3812 static void do_disconnect(char *arg) | |
3813 { | |
3814 xmpp_disconnect(); | |
3815 } | |
3816 | |
3817 static void do_help(char *arg) | |
3818 { | |
3819 help_process(arg); | |
3820 } | |
3821 | |
3822 static void do_echo(char *arg) | |
3823 { | |
3824 if (arg) | |
3825 scr_print_logwindow(arg); | |
3826 } | |
3827 | |
3828 /* vim: set expandtab cindent cinoptions=>2\:2(0: For Vim users... */ |