From a5d31a195d1e3b682cd57d88a5db7ef0ffa5d492 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Sun, 18 Jun 2000 01:18:12 +0000 Subject: Changed option handling in /commands. Irssi will now complain about unknown options and missing option arguments. Renamed /SERVER -add, -remove and -list to /SERVER ADD, REMOVE and LIST. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@365 dbcabf3a-b0e7-0310-adc4-f8d773084564 --- docs/formats.txt | 7 + docs/manual.txt | 14 +- src/core/commands.c | 324 ++++++++++++++++++---------------- src/core/commands.h | 72 +++++--- src/core/misc.c | 38 +++- src/core/misc.h | 10 +- src/fe-common/core/fe-core-commands.c | 28 ++- src/fe-common/core/fe-log.c | 36 ++-- src/fe-common/core/fe-settings.c | 25 ++- src/fe-common/core/hilight-text.c | 35 ++-- src/fe-common/core/themes.c | 14 +- src/fe-common/irc/dcc/fe-dcc.c | 42 +++-- src/fe-common/irc/fe-channels.c | 37 ++-- src/fe-common/irc/fe-ignore.c | 37 ++-- src/fe-common/irc/fe-irc-commands.c | 52 +++--- src/fe-common/irc/fe-irc-server.c | 104 ++++++----- src/fe-common/irc/fe-ircnet.c | 68 ++++--- src/fe-common/irc/irc-completion.c | 8 +- src/fe-text/gui-textwidget.c | 67 ++++--- src/irc/bot/botnet-connection.c | 8 +- src/irc/bot/botnet-users.c | 49 +++-- src/irc/bot/botnet.c | 22 ++- src/irc/core/bans.c | 9 +- src/irc/core/channels-query.c | 4 +- src/irc/core/channels.c | 8 +- src/irc/core/irc-commands.c | 253 ++++++++++++++++---------- src/irc/core/irc-special-vars.c | 8 +- src/irc/core/ircnet-setup.c | 4 +- src/irc/core/modes.c | 11 +- src/irc/core/netsplit.c | 9 +- src/irc/dcc/dcc-chat.c | 28 +-- src/irc/dcc/dcc-files.c | 40 +++-- src/irc/dcc/dcc.c | 28 +-- src/irc/notifylist/notify-commands.c | 26 ++- 34 files changed, 949 insertions(+), 576 deletions(-) diff --git a/docs/formats.txt b/docs/formats.txt index 633b0e42..cda7d422 100644 --- a/docs/formats.txt +++ b/docs/formats.txt @@ -1,3 +1,6 @@ + + Irssi's colors that you can use in text formats etc. : + text text background --------------------------------------------------------------------- %k %K %0 black bold black black @@ -17,3 +20,7 @@ %| Marks the indentation position %% A single % + MIRC colors that you can use when writing text to channel and with + hilighting text: + + FIXME: list them :) diff --git a/docs/manual.txt b/docs/manual.txt index da5a4f9c..62ffa8df 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -394,7 +394,7 @@ network and Irssi will pick the server for you. You don't need to specify the IRC network, password, nick, etc. if - you setup the server using /SERVER -add (see next section). If the + you setup the server using /SERVER ADD (see next section). If the settings can't be found there either, Irssi will use the defaults: /SET default_nick = , defaults to user_name @@ -424,9 +424,9 @@ 5.4 Server settings - /SERVER -add [-auto | -noauto] [-ircnet ] [-host ] - [-cmdspeed ] [-cmdmax ] [-port ] -
[ []] + /SERVER ADD [-auto | -noauto] [-ircnet ] [-host ] + [-cmdspeed ] [-cmdmax ] [-port ] +
[ []] -auto: Automatically connect to server at startup (default) -noauto: Don't connect to server at startup @@ -437,9 +437,9 @@ -port: This is pretty much like the port argument later, except this can be used to modify existing server's port. - /SERVER -remove
[] + /SERVER REMOVE
[] - /SERVER -list + /SERVER LIST Servers are identified by their name and port. You can have multiple entries for the same server name but in different ports. This is @@ -450,7 +450,7 @@ -port command. For example if you had irc.server.org in port 6667 and you wanted to change it to port 6668, use command: - /SERVER -add -port 6668 irc.server.org 6667 + /SERVER ADD -port 6668 irc.server.org 6667 If you want to remove some settings from existing server, for example hostname, just give -host "" parameters to it. diff --git a/src/core/commands.c b/src/core/commands.c index 225f8213..5e0a27ba 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -66,6 +66,7 @@ void command_free(COMMAND_REC *rec) signal_emit("commandlist remove", 1, rec); g_free_not_null(rec->category); + g_strfreev(rec->options); g_free(rec->cmd); g_free(rec); } @@ -93,7 +94,7 @@ void command_unbind(const char *cmd, SIGNAL_FUNC func) } } -void command_runsub(const char *cmd, const char *data, void *p1, void *p2) +void command_runsub(const char *cmd, const char *data, void *server, void *item) { char *subcmd, *defcmd, *args; @@ -106,30 +107,101 @@ void command_runsub(const char *cmd, const char *data, void *p1, void *p2) while (*args == ' ') args++; g_strdown(subcmd); - if (!signal_emit(subcmd, 3, args, p1, p2)) { + if (!signal_emit(subcmd, 3, args, server, item)) { defcmd = g_strdup_printf("default command %s", cmd); - if (!signal_emit(defcmd, 3, data, p1, p2)) - signal_emit("unknown command", 3, strchr(subcmd, ' ')+1, p1, p2); + if (!signal_emit(defcmd, 3, data, server, item)) + signal_emit("unknown command", 3, strchr(subcmd, ' ')+1, server, item); g_free(defcmd); } g_free(subcmd); } -COMMAND_REC *command_find(const char *command) +COMMAND_REC *command_find(const char *cmd) { GSList *tmp; - int len; + + g_return_val_if_fail(cmd != NULL, NULL); for (tmp = commands; tmp != NULL; tmp = tmp->next) { COMMAND_REC *rec = tmp->data; - if (g_strcasecmp(rec->cmd, command) == 0) + if (g_strcasecmp(rec->cmd, cmd) == 0) return rec; } return NULL; } +#define iscmdtype(c) \ + ((c) == '-' || (c) == '+' || (c) == '@') + +static GSList *optlist_find(GSList *optlist, const char *option) +{ + while (optlist != NULL) { + char *name = optlist->data; + if (iscmdtype(*name)) name++; + + if (g_strcasecmp(name, option) == 0) + return optlist; + + optlist = optlist->next; + } + + return NULL; +} + +void command_set_options(const char *cmd, const char *options) +{ + COMMAND_REC *rec; + char **optlist, **tmp, *name, *str; + GSList *list, *oldopt; + + g_return_if_fail(cmd != NULL); + g_return_if_fail(options != NULL); + + rec = command_find(cmd); + g_return_if_fail(rec != NULL); + + optlist = g_strsplit(options, " ", -1); + + if (rec->options == NULL) { + /* first call - use specified args directly */ + rec->options = optlist; + return; + } + + /* save old options to linked list */ + list = NULL; + for (tmp = rec->options; *tmp != NULL; tmp++) + list = g_slist_append(list, g_strdup(*tmp)); + g_strfreev(rec->options); + + /* merge the options */ + for (tmp = optlist; *tmp != NULL; tmp++) { + name = iscmdtype(**tmp) ? (*tmp)+1 : *tmp; + + oldopt = optlist_find(list, name); + if (oldopt != NULL) { + /* already specified - overwrite old defination */ + g_free(oldopt->data); + oldopt->data = g_strdup(*tmp); + } else { + /* new option, append to list */ + list = g_slist_append(list, g_strdup(*tmp)); + } + } + g_strfreev(optlist); + + /* linked list -> string[] */ + g_free(rec->options); + str = gslist_to_string(list, " "); + rec->options = g_strsplit(str, " ", -1); + g_free(str); + + g_slist_foreach(list, (GFunc) g_free, NULL); + g_slist_free(list); +} + char *cmd_get_param(char **data) { char *pos; @@ -146,7 +218,7 @@ char *cmd_get_param(char **data) return pos; } -char *cmd_get_quoted_param(char **data) +static char *cmd_get_quoted_param(char **data) { char *pos, quote; @@ -171,67 +243,7 @@ char *cmd_get_quoted_param(char **data) return pos; } -static char *get_opt_args(char **data) -{ - /* -cmd1 -cmd2 -cmd3 ... */ - char *p, *ret; - int stopnext; - - g_return_val_if_fail(data != NULL, NULL); - g_return_val_if_fail(*data != NULL, NULL); - - stopnext = FALSE; - ret = NULL; - for (p = *data;;) { - if (*p != '-' || stopnext) { - if (p == *data) return ""; - - ret = *data; - *data = p; - - while (isspace(p[-1]) && p > ret) p--; - if (*p != '\0') *p = '\0'; - return ret; - } - - if (p[1] == '-') { - /* -- argument means end of arguments even if - next word starts with - */ - stopnext = TRUE; - } - - while (!isspace(*p) && *p != '\0') p++; - while (isspace(*p)) p++; - } -} - -static void cmd_params_pack(char ***subargs, char *end, char *start, char *newstart) -{ - char ***tmp; - char *data; - int bufsize, datalen, len; - - bufsize = (int) (end-newstart)+1; - - data = g_malloc(bufsize); datalen = 0; - for (tmp = subargs; *tmp != NULL; tmp++) { - if (**tmp < start || **tmp > end) - continue; - - len = strlen(**tmp)+1; - if (datalen+len > bufsize) - g_error("cmd_params_pack() : buffer overflow!"); - - memcpy(data+datalen, **tmp, len); - **tmp = newstart+datalen; - datalen += len; - } - - g_memmove(newstart, data, datalen); - g_free(data); -} - -int arg_find(char **array, const char *item) +static int option_find(char **array, const char *item) { char **tmp; int index; @@ -241,101 +253,83 @@ int arg_find(char **array, const char *item) index = 0; for (tmp = array; *tmp != NULL; tmp++, index++) { - if (g_strcasecmp(*tmp + (**tmp == '@'), item) == 0) + if (g_strcasecmp(*tmp + iscmdtype(**tmp), item) == 0) return index; } return -1; } -static int get_multi_args(char **data, int checkonly, va_list va) +static int get_cmd_options(char **data, int ignore_unknown, + const char *cmd, GHashTable *options) { - /* -cmd1 arg1 -cmd2 "argument two" -cmd3 */ - GString *returnargs; - char **args, **arglist, *arg, *origdata; - char **nextarg, ***subargs; - int eat, pos; - - eat = 0; - args = (char **) va_arg(va, char **); - g_return_val_if_fail(args != NULL && *args != NULL && **args != '\0', 0); - - arglist = g_strsplit(*args, " ", -1); - eat = strarray_length(arglist); - - subargs = g_new(char **, eat+1); - for (pos = 0; pos < eat; pos++) { - subargs[pos] = (char **) va_arg(va, char **); - if (subargs[pos] == NULL) { - g_free(subargs); - g_warning("get_multi_args() : subargument == NULL"); - return eat; - } - *subargs[pos] = ""; - } - subargs[eat] = NULL; + COMMAND_REC *rec; + char *option, *arg, **optlist; + int pos; - origdata = *data; - returnargs = g_string_new(NULL); - nextarg = NULL; + /* get option definations */ + rec = cmd == NULL ? NULL : command_find(cmd); + optlist = rec == NULL ? NULL : rec->options; + + option = NULL; pos = -1; for (;;) { if (**data == '-') { + if (option != NULL && *optlist[pos] == '+') { + /* required argument missing! */ + *data = optlist[pos] + 1; + return CMDERR_OPTION_ARG_MISSING; + } + (*data)++; if (**data == '-') { - /* -- argument means end of arguments even + /* -- option means end of options even if next word starts with - */ (*data)++; while (isspace(**data)) (*data)++; break; } - arg = cmd_get_param(data); - g_string_sprintfa(returnargs, "-%s ", arg); + option = cmd_get_param(data); - /* check if this argument can have parameter */ - pos = arg_find(arglist, arg); - nextarg = pos == -1 ? NULL : subargs[pos]; + /* check if this option can have argument */ + pos = optlist == NULL ? -1 : option_find(optlist, option); + if (pos == -1 && !ignore_unknown) { + /* unknown option! */ + *data = option; + return CMDERR_OPTION_UNKNOWN; + } + if (pos != -1) { + /* if we used a shortcut of parameter, put + the whole parameter name in options table */ + option = optlist[pos] + iscmdtype(*optlist[pos]); + } + if (options != NULL) g_hash_table_insert(options, option, ""); + + if (pos == -1 || !iscmdtype(*optlist[pos])) + option = NULL; while (isspace(**data)) (*data)++; continue; } - if (nextarg == NULL) + if (option == NULL) break; - if (*arglist[pos] == '@' && !isdigit(**data)) + if (*optlist[pos] == '@' && !isdigit(**data)) break; /* expected a numeric argument */ - /* save the sub-argument to `nextarg' */ + /* save the argument */ arg = cmd_get_quoted_param(data); - *nextarg = arg; nextarg = NULL; + if (options != NULL) { + g_hash_table_remove(options, option); + g_hash_table_insert(options, option, arg); + } + option = NULL; while (isspace(**data)) (*data)++; } - if (!checkonly) { - /* ok, this is a bit stupid. this will pack the arguments in - `data' like "-arg1 subarg -arg2 sub2\0" -> - "-arg1 -arg2\0subarg\0sub2\0" this is because it's easier - to free only _one_ string instead of two (`args') when - using PARAM_FLAG_MULTIARGS. */ - if (returnargs->len == 0) - *args = ""; - else { - cmd_params_pack(subargs, **data == '\0' ? *data : (*data)-1, - origdata, origdata+returnargs->len); - - g_string_truncate(returnargs, returnargs->len-1); - strcpy(origdata, returnargs->str); - *args = origdata; - } - } - - g_string_free(returnargs, TRUE); - g_strfreev(arglist); - g_free(subargs); - - return eat; + return 0; } char *cmd_get_callfuncs(const char *data, int *count, va_list *args) @@ -356,34 +350,38 @@ char *cmd_get_callfuncs(const char *data, int *count, va_list *args) return ret; } -char *cmd_get_params(const char *data, int count, ...) +typedef struct { + char *data; + GHashTable *options; +} CMD_TEMP_REC; + +int cmd_get_params(const char *data, gpointer *free_me, int count, ...) { + CMD_TEMP_REC *rec; + GHashTable **opthash; char **str, *arg, *datad, *old; va_list args; - int cnt, eat, len; + int cnt, error, len; - g_return_val_if_fail(data != NULL, NULL); + g_return_val_if_fail(data != NULL, FALSE); va_start(args, count); - /* get the length of the arguments in string */ - if ((count & (PARAM_FLAG_MULTIARGS|PARAM_FLAG_OPTARGS)) == 0) + /* get the length of the options in string */ + if ((count & PARAM_FLAG_OPTIONS) == 0) len = 0; else { old = datad = g_strdup(data); - if (count & PARAM_FLAG_MULTIARGS) - get_multi_args(&datad, TRUE, args); - else - get_opt_args(&datad); + get_cmd_options(&datad, TRUE, NULL, NULL); len = (int) (datad-old); g_free(old); } - /* send the text to custom functions to handle - skip arguments */ + /* send the text to custom functions to handle - skip options */ old = datad = cmd_get_callfuncs(data+len, &count, &args); if (len > 0) { - /* put the arguments + the new data to one string */ + /* put the options + the new data to one string */ datad = g_malloc(len+1 + strlen(old)+1); memcpy(datad, data, len); datad[len] = ' '; @@ -393,20 +391,25 @@ char *cmd_get_params(const char *data, int count, ...) old = datad; } + rec = g_new0(CMD_TEMP_REC, 1); + rec->data = old; + *free_me = rec; + /* and now handle the string */ + error = FALSE; cnt = PARAM_WITHOUT_FLAGS(count); while (cnt-- > 0) { - if (count & PARAM_FLAG_MULTIARGS) { - eat = get_multi_args(&datad, FALSE, args)+1; - count &= ~PARAM_FLAG_MULTIARGS; + if (count & PARAM_FLAG_OPTIONS) { + arg = (char *) va_arg(args, char *); + opthash = (GHashTable **) va_arg(args, GHashTable **); - cnt -= eat-1; - while (eat-- > 0) - str = (char **) va_arg(args, char **); + rec->options = *opthash = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); + error = get_cmd_options(&datad, count & PARAM_FLAG_UNKNOWN_OPTIONS, arg, *opthash); + if (error) break; + + count &= ~PARAM_FLAG_OPTIONS; + cnt++; continue; - } else if (count & PARAM_FLAG_OPTARGS) { - arg = get_opt_args(&datad); - count &= ~PARAM_FLAG_OPTARGS; } else if (cnt == 0 && count & PARAM_FLAG_GETREST) { /* get rest */ arg = datad; @@ -421,7 +424,24 @@ char *cmd_get_params(const char *data, int count, ...) } va_end(args); - return old; + if (error) { + signal_emit("error command", 2, GINT_TO_POINTER(error), datad); + signal_stop(); + + cmd_params_free(rec); + *free_me = NULL; + } + + return !error; +} + +void cmd_params_free(void *free_me) +{ + CMD_TEMP_REC *rec = free_me; + + if (rec->options != NULL) g_hash_table_destroy(rec->options); + g_free(rec->data); + g_free(rec); } void cmd_get_add_func(CMD_GET_FUNC func) diff --git a/src/core/commands.h b/src/core/commands.h index 42fb20c0..a199a1f5 100644 --- a/src/core/commands.h +++ b/src/core/commands.h @@ -6,10 +6,13 @@ typedef struct { char *category; char *cmd; -} -COMMAND_REC; + char **options; +} COMMAND_REC; enum { + CMDERR_OPTION_UNKNOWN = -2, /* unknown -option */ + CMDERR_OPTION_ARG_MISSING = -1, /* argument missing for -option */ + CMDERR_ERRNO, /* get the error from errno */ CMDERR_NOT_ENOUGH_PARAMS, /* not enough parameters given */ CMDERR_NOT_CONNECTED, /* not connected to IRC server */ @@ -20,7 +23,7 @@ enum { }; #define cmd_return_error(a) { signal_emit("error command", 1, GINT_TO_POINTER(a)); signal_stop(); return; } -#define cmd_param_error(a) { g_free(params); cmd_return_error(a); } +#define cmd_param_error(a) { cmd_params_free(free_arg); cmd_return_error(a); } extern GSList *commands; extern char *current_command; @@ -29,12 +32,29 @@ void command_bind_to(int pos, const char *cmd, const char *category, SIGNAL_FUNC #define command_bind(a, b, c) command_bind_to(1, a, b, c) #define command_bind_first(a, b, c) command_bind_to(0, a, b, c) #define command_bind_last(a, b, c) command_bind_to(2, a, b, c) - void command_unbind(const char *cmd, SIGNAL_FUNC func); -void command_runsub(const char *cmd, const char *data, void *p1, void *p2); +/* Run subcommand, `cmd' contains the base command, first word in `data' + contains the subcommand */ +void command_runsub(const char *cmd, const char *data, void *server, void *item); + +COMMAND_REC *command_find(const char *cmd); + +/* Specify options that command can accept. `options' contains list of + options separated with space, each option can contain a special + char in front of it: + + '-': optional argument + '+': argument required + '@': optional numeric argument -COMMAND_REC *command_find(const char *command); + for example if options = "save -file +nick", you can use + /command -save -file [] -nick + + You can call this command multiple times for same command, options + will be merged. If there's any conflicts with option types, the last + call will override the previous */ +void command_set_options(const char *cmd, const char *options); /* count can have these flags: */ #define PARAM_WITHOUT_FLAGS(a) ((a) & 0x00ffffff) @@ -42,30 +62,40 @@ COMMAND_REC *command_find(const char *command); #define PARAM_FLAG_NOQUOTES 0x01000000 /* final argument gets all the rest of the arguments */ #define PARAM_FLAG_GETREST 0x02000000 -/* optional arguments (-cmd -cmd2 -cmd3) */ -#define PARAM_FLAG_OPTARGS 0x04000000 -/* arguments can have arguments too. Example: +/* command contains options - first you need to specify them with + command_set_options() function. Example: - -cmd arg -noargcmd -cmd2 "another arg -optnumarg rest of the text + -cmd requiredarg -noargcmd -cmd2 "another arg" -optnumarg rest of text You would call this with: - args = "cmd cmd2 @optnumarg"; - cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST, - &args, &arg_cmd, &arg_cmd2, &arg_optnum, &rest); + // only once in init + command_set_options("mycmd", "+cmd noargcmd -cmd2 @optnumarg"); + + GHashTable *optlist; + + cmd_get_params(data, &free_me, 1 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_GETREST, "mycmd", &optlist, &rest); - The variables are filled as following: + The optlist hash table is filled: - args = "-cmd -noargcmd -cmd2 -optnumarg" - arg_cmd = "arg" - arg_cmd2 = "another arg" - rest = "rest of the text" - arg_optnum = "" - this is because "rest" isn't a numeric value + "cmd" = "requiredarg" + "noargcmd" = "" + "cmd2" = "another arg" + "optnumarg" = "" - this is because "rest" isn't a numeric value */ -#define PARAM_FLAG_MULTIARGS 0x08000000 +#define PARAM_FLAG_OPTIONS 0x04000000 +/* don't complain about unknown options */ +#define PARAM_FLAG_UNKNOWN_OPTIONS 0x08000000 char *cmd_get_param(char **data); -char *cmd_get_params(const char *data, int count, ...); +/* get parameters from command - you should point free_me somewhere and + cmd_params_free() it after you don't use any of the parameters anymore. + + Returns TRUE if all ok, FALSE if error occured. */ +int cmd_get_params(const char *data, gpointer *free_me, int count, ...); + +void cmd_params_free(void *free_me); typedef char* (*CMD_GET_FUNC) (const char *data, int *count, va_list *args); void cmd_get_add_func(CMD_GET_FUNC func); diff --git a/src/core/misc.c b/src/core/misc.c index bc73f5a0..952c7149 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -247,7 +247,8 @@ void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, void *data) return NULL; } -char *gslist_to_string(GSList *list, int offset, const char *delimiter) +/* `list' contains pointer to structure with a char* to string. */ +char *gslistptr_to_string(GSList *list, int offset, const char *delimiter) { GString *str; char **data, *ret; @@ -266,6 +267,41 @@ char *gslist_to_string(GSList *list, int offset, const char *delimiter) return ret; } +/* `list' contains char* */ +char *gslist_to_string(GSList *list, const char *delimiter) +{ + GString *str; + char *ret; + + str = g_string_new(NULL); + while (list != NULL) { + if (str->len != 0) g_string_append(str, delimiter); + g_string_append(str, list->data); + + list = list->next; + } + + ret = str->str; + g_string_free(str, FALSE); + return ret; +} + +void hash_save_key(char *key, void *value, GSList **list) +{ + *list = g_slist_append(*list, key); +} + +/* save all keys in hash table to linked list - you shouldn't remove any + items while using this list, use g_slist_free() after you're done with it */ +GSList *hashtable_get_keys(GHashTable *hash) +{ + GSList *list; + + list = NULL; + g_hash_table_foreach(hash, (GHFunc) hash_save_key, &list); + return list; +} + GList *glist_find_string(GList *list, const char *key) { for (list = list; list != NULL; list = list->next) diff --git a/src/core/misc.h b/src/core/misc.h index 3df1dc94..7fa866df 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -25,7 +25,15 @@ GList *glist_find_string(GList *list, const char *key); GList *glist_find_icase_string(GList *list, const char *key); void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, void *data); -char *gslist_to_string(GSList *list, int offset, const char *delimiter); + +/* `list' contains pointer to structure with a char* to string. */ +char *gslistptr_to_string(GSList *list, int offset, const char *delimiter); +/* `list' contains char* */ +char *gslist_to_string(GSList *list, const char *delimiter); + +/* save all keys in hash table to linked list - you shouldn't remove any + items while using this list, use g_slist_free() after you're done with it */ +GSList *hashtable_get_keys(GHashTable *hash); /* strstr() with case-ignoring */ char *stristr(const char *data, const char *key); diff --git a/src/fe-common/core/fe-core-commands.c b/src/fe-common/core/fe-core-commands.c index 4de1ae6a..3b725bae 100644 --- a/src/fe-common/core/fe-core-commands.c +++ b/src/fe-common/core/fe-core-commands.c @@ -31,7 +31,7 @@ #include "windows.h" static const char *ret_texts[] = { - NULL, + NULL, "Not enough parameters given", "Not connected to IRC server yet", "Not joined to any channels yet", @@ -230,15 +230,18 @@ static void cmd_version(char *data) static void cmd_cat(const char *data) { - char *params, *fname, *fposstr; - char tmpbuf[1024], *str; LINEBUF_REC *buffer = NULL; + char *fname, *fposstr; + char tmpbuf[1024], *str; + void *free_arg; int f, ret, recvlen, fpos; - params = cmd_get_params(data, 2, &fname, &fposstr); + if (!cmd_get_params(data, &free_arg, 2, &fname, &fposstr)) + return; + fname = convert_home(fname); fpos = atoi(fposstr); - g_free(params); + cmd_params_free(free_arg); f = open(fname, O_RDONLY); g_free(fname); @@ -301,15 +304,24 @@ static void event_default_command(const char *data, void *server, WI_ITEM_REC *i cmd_unknown(data, server, item); } -static void event_cmderror(gpointer errorp) +static void event_cmderror(gpointer errorp, const char *arg) { int error; error = GPOINTER_TO_INT(errorp); - if (error == CMDERR_ERRNO) + switch (error) { + case CMDERR_ERRNO: printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, g_strerror(errno)); - else + break; + case CMDERR_OPTION_UNKNOWN: + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown argument: %s", arg); + break; + case CMDERR_OPTION_ARG_MISSING: + printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Missing required argument for: %s", arg); + break; + default: printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[error]); + } } void fe_core_commands_init(void) diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index c66859b3..1da7e229 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -45,18 +45,24 @@ static void cmd_log_open(const char *data) { /* /LOG OPEN [-noopen] [-autoopen] [-targets ] [-window] [-rotate hour|day|week|month] [] */ - char *params, *args, *targetarg, *rotatearg, *fname, *levels; + GHashTable *optlist; + char *targetarg, *rotatearg, *fname, *levels; + void *free_arg; char window[MAX_INT_STRLEN]; LOG_REC *log; int level, rotate; - args = "targets rotate"; - params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST, - &args, &targetarg, &rotatearg, &fname, &levels); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, + "log open", &optlist, &fname, &levels)) + return; + + targetarg = g_hash_table_lookup(optlist, "targets"); + rotatearg = g_hash_table_lookup(optlist, "rotate"); + if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); rotate = LOG_ROTATE_NEVER; - if (stristr(args, "-rotate")) { + if (rotatearg != NULL) { rotate = log_str2rotate(rotatearg); if (rotate < 0) rotate = LOG_ROTATE_NEVER; } @@ -64,7 +70,7 @@ static void cmd_log_open(const char *data) level = level2bits(levels); if (level == 0) level = MSGLEVEL_ALL; - if (stristr(args, "-window")) { + if (g_hash_table_lookup(optlist, "window")) { /* log by window ref# */ ltoa(window, active_win->refnum); targetarg = window; @@ -72,12 +78,12 @@ static void cmd_log_open(const char *data) log = log_create_rec(fname, level, targetarg); if (log != NULL) { - if (stristr(args, "-autoopen")) + if (g_hash_table_lookup(optlist, "autoopen")) log->autoopen = TRUE; log->rotate = rotate; log_update(log); - if (log->handle == -1 && stristr(args, "-noopen") == NULL) { + if (log->handle == -1 && g_hash_table_lookup(optlist, "noopen") == NULL) { /* start logging */ if (log_start_logging(log)) { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, @@ -88,7 +94,7 @@ static void cmd_log_open(const char *data) } } - g_free(params); + cmd_params_free(free_arg); } static LOG_REC *log_find_from_data(const char *data) @@ -191,10 +197,12 @@ static void cmd_window_log(const char *data) { /* /WINDOW LOG ON|OFF|TOGGLE [] */ LOG_REC *log; - char *params, *set, *fname, window[MAX_INT_STRLEN]; + char *set, *fname, window[MAX_INT_STRLEN]; + void *free_arg; int open_log, close_log; - params = cmd_get_params(data, 2, &set, &fname); + if (!cmd_get_params(data, &free_arg, 2, &set, &fname)) + return; ltoa(window, active_win->refnum); log = log_find_item(window); @@ -209,7 +217,7 @@ static void cmd_window_log(const char *data) close_log = log != NULL; } else { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOT_TOGGLE); - g_free(params); + cmd_params_free(free_arg); return; } @@ -232,7 +240,7 @@ static void cmd_window_log(const char *data) printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_CLOSED, log->fname); } - g_free(params); + cmd_params_free(free_arg); } /* Create log file entry to window, but don't start logging */ @@ -440,6 +448,8 @@ void fe_log_init(void) signal_add("log create failed", (SIGNAL_FUNC) sig_log_create_failed); signal_add("awaylog show", (SIGNAL_FUNC) sig_awaylog_show); signal_add("setup changed", (SIGNAL_FUNC) read_settings); + + command_set_options("log open", "noopen autoopen -targets window -rotate"); } void fe_log_deinit(void) diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index f05faad0..299f437e 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -66,10 +66,12 @@ static void set_boolean(const char *key, const char *value) static void cmd_set(char *data) { GSList *sets, *tmp; - char *params, *key, *value, *last_section; + char *key, *value, *last_section; + void *free_arg; int found; - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value)) + return; last_section = ""; found = 0; sets = settings_get_sorted(); @@ -110,15 +112,17 @@ static void cmd_set(char *data) if (!found) printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown setting %s", key); - g_free(params); + cmd_params_free(free_arg); } static void cmd_toggle(const char *data) { - char *params, *key, *value; + char *key, *value; + void *free_arg; int type; - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value)) + return; type = settings_get_type(key); if (type == -1) @@ -130,7 +134,7 @@ static void cmd_toggle(const char *data) set_print(settings_get_record(key)); } - g_free(params); + cmd_params_free(free_arg); } static void show_aliases(const char *alias) @@ -173,11 +177,14 @@ static void alias_remove(const char *alias) static void cmd_alias(const char *data) { - char *params, *alias, *value; + char *alias, *value; + void *free_arg; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &alias, &value); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &alias, &value)) + return; + if (*alias == '-') { if (alias[1] != '\0') alias_remove(alias+1); } else if (*alias == '\0' || *value == '\0') @@ -186,7 +193,7 @@ static void cmd_alias(const char *data) printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_ALIAS_ADDED, alias); iconfig_set_str("aliases", alias, value); } - g_free(params); + cmd_params_free(free_arg); } static void cmd_unalias(const char *data) diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index f78d8904..d2da11cd 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -268,9 +268,11 @@ static void cmd_hilight_show(void) static void cmd_hilight(const char *data) { /* /HILIGHT [-nick | -regexp | -word] [-color ] [-level ] [-channels ] */ - char *params, *args, *colorarg, *levelarg, *chanarg, *text; - char **channels; + GHashTable *optlist; HILIGHT_REC *rec; + char *colorarg, *levelarg, *chanarg, *text; + char **channels; + void *free_arg; g_return_if_fail(data != NULL); @@ -279,12 +281,17 @@ static void cmd_hilight(const char *data) return; } - args = "color level channels"; - params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST, - &args, &colorarg, &levelarg, &chanarg, &text); + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_GETREST, "hilight", &optlist, &text)) + return; + + chanarg = g_hash_table_lookup(optlist, "channels"); + levelarg = g_hash_table_lookup(optlist, "level"); + colorarg = g_hash_table_lookup(optlist, "color"); + if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - channels = *chanarg == '\0' ? NULL : + channels = (chanarg == NULL || *chanarg == '\0') ? NULL : g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1); rec = hilight_find(text, channels); @@ -302,17 +309,19 @@ static void cmd_hilight(const char *data) } hilights = g_slist_append(hilights, rec); - rec->nickmask = stristr(args, "-nick") != NULL; - rec->fullword = stristr(args, "-word") != NULL; - rec->regexp = stristr(args, "-regexp") != NULL; + rec->nickmask = g_hash_table_lookup(optlist, "nick") != NULL; + rec->fullword = g_hash_table_lookup(optlist, "word") != NULL; + rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL; - rec->level = level2bits(replace_chars(levelarg, ',', ' ')); - if (*colorarg != '\0') rec->color = g_strdup(colorarg); + rec->level = (levelarg == NULL || *levelarg == '\0') ? 0 : + level2bits(replace_chars(levelarg, ',', ' ')); + if (colorarg != NULL && *colorarg != '\0') + rec->color = g_strdup(colorarg); hilight_print(g_slist_index(hilights, rec)+1, rec); hilight_add_config(rec); - g_free(params); + cmd_params_free(free_arg); } static void cmd_dehilight(const char *data) @@ -349,6 +358,8 @@ void hilight_text_init(void) signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config); command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight); command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight); + + command_set_options("hilight", "-color -level -channels nick word regexp"); } void hilight_text_deinit(void) diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c index 879f558c..efe905bf 100644 --- a/src/fe-common/core/themes.c +++ b/src/fe-common/core/themes.c @@ -348,17 +348,21 @@ static void theme_show(THEME_SEARCH_REC *rec, const char *key, const char *value static void cmd_format(const char *data) { - char *params, *module, *key, *value; GSList *tmp, *modules; + char *module, *key, *value; + void *free_arg; /* /FORMAT [] [ []] */ - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &module, &key, &value); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, + &module, &key, &value)) + return; modules = get_sorted_modules(); if (*module != '\0' && theme_search(modules, module) == NULL) { /* first argument isn't module.. */ - g_free(params); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value); + cmd_params_free(free_arg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &key, &value)) + return; module = ""; } @@ -374,7 +378,7 @@ static void cmd_format(const char *data) g_slist_foreach(modules, (GFunc) g_free, NULL); g_slist_free(modules); - g_free(params); + cmd_params_free(free_arg); } static void module_save(const char *module, MODULE_THEME_REC *rec, CONFIG_NODE *fnode) diff --git a/src/fe-common/irc/dcc/fe-dcc.c b/src/fe-common/irc/dcc/fe-dcc.c index f67add7c..d128a332 100644 --- a/src/fe-common/irc/dcc/fe-dcc.c +++ b/src/fe-common/irc/dcc/fe-dcc.c @@ -231,24 +231,28 @@ static void dcc_error_close_not_found(const char *type, const char *nick, const static void dcc_unknown_ctcp(const char *data, const char *sender) { - char *params, *type, *args; + char *type, *args; + void *free_arg; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &type, &args); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &type, &args)) + return; printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_CTCP, type, sender, args); - g_free(params); + cmd_params_free(free_arg); } static void dcc_unknown_reply(const char *data, const char *sender) { - char *params, *type, *args; + char *type, *args; + void *free_arg; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &type, &args); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &type, &args)) + return; printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_REPLY, type, sender, args); - g_free(params); + cmd_params_free(free_arg); } static void sig_dcc_destroyed(DCC_REC *dcc) @@ -288,7 +292,8 @@ static void sig_query_destroyed(QUERY_REC *query) static void cmd_msg(const char *data) { DCC_REC *dcc; - char *params, *text, *target; + char *text, *target; + void *free_arg; g_return_if_fail(data != NULL); @@ -297,7 +302,8 @@ static void cmd_msg(const char *data) return; } - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &text); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text)) + return; dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL); if (dcc == NULL) { @@ -309,7 +315,7 @@ static void cmd_msg(const char *data) IRCTXT_OWN_DCC, dcc->mynick, text); } - g_free(params); + cmd_params_free(free_arg); } static void cmd_me(const char *data, SERVER_REC *server, WI_IRC_REC *item) @@ -327,8 +333,9 @@ static void cmd_me(const char *data, SERVER_REC *server, WI_IRC_REC *item) static void cmd_action(const char *data, SERVER_REC *server, WI_IRC_REC *item) { - char *params, *target, *text; DCC_REC *dcc; + char *target, *text; + void *free_arg; g_return_if_fail(data != NULL); @@ -337,7 +344,8 @@ static void cmd_action(const char *data, SERVER_REC *server, WI_IRC_REC *item) return; } - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &text)) + return; if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL); @@ -348,23 +356,25 @@ static void cmd_action(const char *data, SERVER_REC *server, WI_IRC_REC *item) printformat(NULL, target, MSGLEVEL_DCC, IRCTXT_OWN_DCC_ME, dcc->mynick, text); } - g_free(params); + cmd_params_free(free_arg); } static void cmd_ctcp(const char *data, SERVER_REC *server) { - char *params, *target, *ctcpcmd, *ctcpdata; DCC_REC *dcc; + char *target, *ctcpcmd, *ctcpdata; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) + return; if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*target != '=') { /* handle only DCC CTCPs */ - g_free(params); + cmd_params_free(free_arg); return; } @@ -378,7 +388,7 @@ static void cmd_ctcp(const char *data, SERVER_REC *server) target, ctcpcmd, ctcpdata); } - g_free(params); + cmd_params_free(free_arg); } static void cmd_dcc_list(const char *data) diff --git a/src/fe-common/irc/fe-channels.c b/src/fe-common/irc/fe-channels.c index 7cf4f5eb..c17325eb 100644 --- a/src/fe-common/irc/fe-channels.c +++ b/src/fe-common/irc/fe-channels.c @@ -192,12 +192,17 @@ static void cmd_channel(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *i static void cmd_channel_add(const char *data) { - char *params, *args, *botarg, *botcmdarg, *ircnet, *channel, *password; + GHashTable *optlist; SETUP_CHANNEL_REC *rec; + char *botarg, *botcmdarg, *ircnet, *channel, *password; + void *free_arg; - args = "bots botcmd"; - params = cmd_get_params(data, 6 | PARAM_FLAG_MULTIARGS, &args, - &botarg, &botcmdarg, &channel, &ircnet, &password); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS, + "channel add", &optlist, &channel, &ircnet, &password)) + return; + + botarg = g_hash_table_lookup(optlist, "bots"); + botcmdarg = g_hash_table_lookup(optlist, "botcmd"); if (*ircnet == '\0' || *channel == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -207,27 +212,29 @@ static void cmd_channel_add(const char *data) rec->name = g_strdup(channel); rec->ircnet = g_strdup(ircnet); } else { - if (stristr(args, "-bots")) g_free_and_null(rec->botmasks); - if (stristr(args, "-botcmd")) g_free_and_null(rec->autosendcmd); + if (g_hash_table_lookup(optlist, "bots")) g_free_and_null(rec->botmasks); + if (g_hash_table_lookup(optlist, "botcmd")) g_free_and_null(rec->autosendcmd); if (*password != '\0') g_free_and_null(rec->password); } - if (stristr(args, "-auto")) rec->autojoin = TRUE; - if (stristr(args, "-noauto")) rec->autojoin = FALSE; - if (*botarg != '\0') rec->botmasks = g_strdup(botarg); - if (*botcmdarg != '\0') rec->autosendcmd = g_strdup(botcmdarg); + if (g_hash_table_lookup(optlist, "auto")) rec->autojoin = TRUE; + if (g_hash_table_lookup(optlist, "noauto")) rec->autojoin = FALSE; + if (botarg != NULL && *botarg != '\0') rec->botmasks = g_strdup(botarg); + if (botcmdarg != NULL && *botcmdarg != '\0') rec->autosendcmd = g_strdup(botcmdarg); if (*password != '\0' && strcmp(password, "-") != 0) rec->password = g_strdup(password); channels_setup_create(rec); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CHANSETUP_ADDED, channel, ircnet); - g_free(params); + cmd_params_free(free_arg); } static void cmd_channel_remove(const char *data) { - char *params, *ircnet, *channel; SETUP_CHANNEL_REC *rec; + char *ircnet, *channel; + void *free_arg; - params = cmd_get_params(data, 2, &channel, &ircnet); + if (!cmd_get_params(data, &free_arg, 2, &channel, &ircnet)) + return; if (*ircnet == '\0' || *channel == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -238,7 +245,7 @@ static void cmd_channel_remove(const char *data) printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CHANSETUP_REMOVED, channel, ircnet); channels_setup_destroy(rec); } - g_free(params); + cmd_params_free(free_arg); } void fe_channels_init(void) @@ -257,6 +264,8 @@ void fe_channels_init(void) command_bind("channel add", NULL, (SIGNAL_FUNC) cmd_channel_add); command_bind("channel remove", NULL, (SIGNAL_FUNC) cmd_channel_remove); command_bind("channel list", NULL, (SIGNAL_FUNC) cmd_channel_list); + + command_set_options("channel add", "auto noauto -bots -botcmd"); } void fe_channels_deinit(void) diff --git a/src/fe-common/irc/fe-ignore.c b/src/fe-common/irc/fe-ignore.c index cbd74244..6366dd98 100644 --- a/src/fe-common/irc/fe-ignore.c +++ b/src/fe-common/irc/fe-ignore.c @@ -137,14 +137,16 @@ static void cmd_ignore_show(void) static void cmd_ignore(const char *data) { /* /IGNORE [-regexp | -word] [-pattern ] [-except] - [-channels ] + [-replies] [-channels ] OR - /IGNORE [-regexp | -word] [-pattern ] [-except] + /IGNORE [-regexp | -word] [-pattern ] [-except] [-replies] */ - char *params, *args, *patternarg, *chanarg, *mask, *levels, *key; - char **channels; + GHashTable *optlist; IGNORE_REC *rec; + char *patternarg, *chanarg, *mask, *levels, *key; + char **channels; + void *free_arg; int new_ignore; if (*data == '\0') { @@ -152,16 +154,20 @@ static void cmd_ignore(const char *data) return; } - args = "pattern channels"; - params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST, - &args, &patternarg, &chanarg, &mask, &levels); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, + "ignore", &optlist, &mask, &levels)) + return; + + patternarg = g_hash_table_lookup(optlist, "pattern"); + chanarg = g_hash_table_lookup(optlist, "channels"); + if (*levels == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (ischannel(*mask)) { chanarg = mask; mask = ""; } - channels = *chanarg == '\0' ? NULL : + channels = (chanarg == NULL || *chanarg == '\0') ? NULL : g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1); rec = ignore_find(NULL, mask, channels); @@ -177,16 +183,17 @@ static void cmd_ignore(const char *data) g_strfreev(channels); } - if (stristr(args, "-except") != NULL) { + if (g_hash_table_lookup(optlist, "except") != NULL) { rec->except_level = combine_level(rec->except_level, levels); } else { ignore_split_levels(levels, &rec->level, &rec->except_level); } - rec->pattern = *patternarg == '\0' ? NULL : g_strdup(patternarg); - rec->regexp = stristr(args, "-regexp") != NULL; - rec->fullword = stristr(args, "-word") != NULL; - rec->replies = stristr(args, "-replies") != NULL; + rec->pattern = (patternarg == NULL || *patternarg == '\0') ? + NULL : g_strdup(patternarg); + rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL; + rec->fullword = g_hash_table_lookup(optlist, "word") != NULL; + rec->replies = g_hash_table_lookup(optlist, "replies") != NULL; if (rec->level == 0 && rec->except_level == 0) { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_UNIGNORED, @@ -204,7 +211,7 @@ static void cmd_ignore(const char *data) else ignore_update_rec(rec); - g_free(params); + cmd_params_free(free_arg); } static void cmd_unignore(const char *data) @@ -242,6 +249,8 @@ void fe_ignore_init(void) { command_bind("ignore", NULL, (SIGNAL_FUNC) cmd_ignore); command_bind("unignore", NULL, (SIGNAL_FUNC) cmd_unignore); + + command_set_options("ignore", "regexp word except replies -pattern -channels"); } void fe_ignore_deinit(void) diff --git a/src/fe-common/irc/fe-irc-commands.c b/src/fe-common/irc/fe-irc-commands.c index 900b0a2c..0e8e111b 100644 --- a/src/fe-common/irc/fe-irc-commands.c +++ b/src/fe-common/irc/fe-irc-commands.c @@ -93,18 +93,20 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) WINDOW_REC *window; CHANNEL_REC *channel; NICK_REC *nickrec; - char *params, *target, *msg, *nickmode, *freestr, *newtarget; + char *target, *msg, *nickmode, *freestr, *newtarget; + void *free_arg; int free_ret; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) + return; if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*target == '=') { /* dcc msg - handled in fe-dcc.c */ - g_free(params); + cmd_params_free(free_arg); return; } @@ -119,7 +121,7 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) if (newtarget == NULL) { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, *target == ',' ? IRCTXT_NO_MSGS_GOT : IRCTXT_NO_MSGS_SENT); - g_free(params); + cmd_params_free(free_arg); signal_stop(); return; } @@ -160,7 +162,7 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) } g_free_not_null(freestr); - g_free(params); + cmd_params_free(free_arg); } static void cmd_me(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) @@ -180,27 +182,31 @@ static void cmd_me(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) static void cmd_action(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *text; + char *target, *text; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &text)) + return; if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); printformat(server, target, MSGLEVEL_ACTIONS, IRCTXT_OWN_ME, server->nick, text); irc_send_cmdv(server, "PRIVMSG %s :\001ACTION %s\001", target, text); - g_free(params); + cmd_params_free(free_arg); } static void cmd_notice(gchar *data, IRC_SERVER_REC *server) { - char *params, *target, *msg; + char *target, *msg; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) + return; if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*target == '@' && ischannel(target[1])) @@ -209,17 +215,19 @@ static void cmd_notice(gchar *data, IRC_SERVER_REC *server) printformat(server, target, MSGLEVEL_NOTICES | MSGLEVEL_NOHILIGHT, IRCTXT_OWN_NOTICE, target, msg); - g_free(params); + cmd_params_free(free_arg); } static void cmd_ctcp(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *ctcpcmd, *ctcpdata; + char *target, *ctcpcmd, *ctcpdata; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) + return; if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*target == '@' && ischannel(target[1])) @@ -228,17 +236,19 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server) g_strup(ctcpcmd); printformat(server, target, MSGLEVEL_CTCPS, IRCTXT_OWN_CTCP, target, ctcpcmd, ctcpdata); - g_free(params); + cmd_params_free(free_arg); } static void cmd_nctcp(const char *data, IRC_SERVER_REC *server) { - gchar *params, *target, *ctcpcmd, *ctcpdata; + char *target, *ctcpcmd, *ctcpdata; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) + return; if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*target == '@' && ischannel(target[1])) @@ -247,19 +257,21 @@ static void cmd_nctcp(const char *data, IRC_SERVER_REC *server) g_strup(ctcpcmd); printformat(server, target, MSGLEVEL_NOTICES, IRCTXT_OWN_NOTICE, target, ctcpcmd, ctcpdata); - g_free(params); + cmd_params_free(free_arg); } static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *channame, *msg; CHANNEL_REC *chanrec; + char *channame, *msg; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg)) + return; if (*msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); chanrec = channel_find(server, channame); @@ -267,7 +279,7 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) printformat(server, chanrec->name, MSGLEVEL_NOTICES, IRCTXT_OWN_WALL, chanrec->name, msg); - g_free(params); + cmd_params_free(free_arg); } static void cmd_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) diff --git a/src/fe-common/irc/fe-irc-server.c b/src/fe-common/irc/fe-irc-server.c index 24c662b4..140284fd 100644 --- a/src/fe-common/irc/fe-irc-server.c +++ b/src/fe-common/irc/fe-irc-server.c @@ -78,17 +78,18 @@ static void print_reconnects(void) } } -static void server_add(const char *data) +static void cmd_server_add(const char *data) { + GHashTable *optlist; SETUP_SERVER_REC *rec; - char *params, *args, *ircnet, *host, *cmdspeed, *cmdmax, *portarg; - char *addr, *portstr, *password; + char *addr, *portstr, *password, *value; + void *free_arg; int port; - args = "ircnet host cmdspeed cmdmax port"; - params = cmd_get_params(data, 9 | PARAM_FLAG_MULTIARGS, - &args, &ircnet, &host, &cmdspeed, &cmdmax, - &portarg, &addr, &portstr, &password); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS, + "server add", &optlist, &addr, &portstr, &password)) + return; + if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); port = *portstr == '\0' ? 6667 : atoi(portstr); @@ -98,39 +99,48 @@ static void server_add(const char *data) rec->address = g_strdup(addr); rec->port = port; } else { - if (*portarg != '\0') rec->port = atoi(portarg); - if (stristr(args, "-ircnet")) g_free_and_null(rec->ircnet); + value = g_hash_table_lookup(optlist, "port"); + if (value != NULL && *value != '\0') rec->port = atoi(value); + + if (g_hash_table_lookup(optlist, "ircnet")) g_free_and_null(rec->ircnet); if (*password != '\0') g_free_and_null(rec->password); - if (stristr(args, "-host")) { + if (g_hash_table_lookup(optlist, "host")) { g_free_and_null(rec->own_host); rec->own_ip = NULL; } } - if (stristr(args, "-auto")) rec->autoconnect = TRUE; - if (stristr(args, "-noauto")) rec->autoconnect = FALSE; - if (*ircnet != '\0') rec->ircnet = g_strdup(ircnet); + if (g_hash_table_lookup(optlist, "auto")) rec->autoconnect = TRUE; + if (g_hash_table_lookup(optlist, "noauto")) rec->autoconnect = FALSE; + if (*password != '\0' && strcmp(password, "-") != 0) rec->password = g_strdup(password); - if (*host != '\0') { - rec->own_host = g_strdup(host); + value = g_hash_table_lookup(optlist, "ircnet"); + if (value != NULL && *value != '\0') rec->ircnet = g_strdup(value); + value = g_hash_table_lookup(optlist, "host"); + if (value != NULL && *value != '\0') { + rec->own_host = g_strdup(value); rec->own_ip = NULL; } - if (*cmdspeed != '\0') rec->cmd_queue_speed = atoi(cmdspeed); - if (*cmdmax != '\0') rec->max_cmds_at_once = atoi(cmdmax); + value = g_hash_table_lookup(optlist, "cmdspeed"); + if (value != NULL && *value != '\0') rec->cmd_queue_speed = atoi(value); + value = g_hash_table_lookup(optlist, "cmdmax"); + if (value != NULL && *value != '\0') rec->max_cmds_at_once = atoi(value); server_setup_add(rec); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_SETUPSERVER_ADDED, addr, port); - g_free(params); + cmd_params_free(free_arg); } -static void server_remove(const char *data) +static void cmd_server_remove(const char *data) { SETUP_SERVER_REC *rec; - char *params, *args, *addr, *portstr; + char *addr, *portstr; + void *free_arg; int port; - params = cmd_get_params(data, 3 | PARAM_FLAG_OPTARGS, &args, &addr, &portstr); + if (!cmd_get_params(data, &free_arg, 2, &addr, &portstr)) + return; if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); port = *portstr == '\0' ? 6667 : atoi(portstr); @@ -142,10 +152,10 @@ static void server_remove(const char *data) printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_SETUPSERVER_REMOVED, addr, port); } - g_free(params); + cmd_params_free(free_arg); } -static void server_list(const char *data) +static void cmd_server_list(const char *data) { GString *str; GSList *tmp; @@ -177,9 +187,11 @@ static void server_list(const char *data) g_string_free(str, TRUE); } -static void cmd_server(const char *data) +static void cmd_server(const char *data, IRC_SERVER_REC *server, void *item) { - char *params, *args, *ircnetarg, *hostarg, *addr; + GHashTable *optlist; + char *addr; + void *free_arg; if (*data == '\0') { print_servers(); @@ -190,36 +202,40 @@ static void cmd_server(const char *data) return; } - args = "ircnet host"; /* should be same as in connect_server() in src/irc/core/irc-commands.c */ - params = cmd_get_params(data, 4 | PARAM_FLAG_MULTIARGS, - &args, &ircnetarg, &hostarg, &addr); - - if (stristr(args, "-list") != NULL) { - server_list(data); - signal_stop(); - } else if (stristr(args, "-add") != NULL) { - if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - server_add(data); + if (g_strncasecmp(data, "add ", 4) == 0 || + g_strncasecmp(data, "remove ", 7) == 0 || + g_strcasecmp(data, "list") == 0 || + g_strncasecmp(data, "list ", 5) == 0) { + command_runsub("server", data, server, item); signal_stop(); - } else if (stristr(args, "-remove") != NULL) { - if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - server_remove(data); - signal_stop(); - } else { - if (*addr == '\0' || strcmp(addr, "+") == 0) - cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - if (*addr == '+') window_create(NULL, FALSE); + return; } - g_free(params); + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, + "connect", &optlist, &addr)) + return; + + if (*addr == '\0' || strcmp(addr, "+") == 0) + cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + if (*addr == '+') window_create(NULL, FALSE); + + cmd_params_free(free_arg); } void fe_irc_server_init(void) { command_bind("server", NULL, (SIGNAL_FUNC) cmd_server); + command_bind("server add", NULL, (SIGNAL_FUNC) cmd_server_add); + command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove); + command_bind("server list", NULL, (SIGNAL_FUNC) cmd_server_list); + + command_set_options("server add", "auto noauto -ircnet -host -cmdspeed -cmdmax -port"); } void fe_irc_server_deinit(void) { command_unbind("server", (SIGNAL_FUNC) cmd_server); + command_unbind("server add", (SIGNAL_FUNC) cmd_server_add); + command_unbind("server remove", (SIGNAL_FUNC) cmd_server_remove); + command_unbind("server list", (SIGNAL_FUNC) cmd_server_list); } diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index 88e1d806..adc4f03c 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -79,15 +79,14 @@ static void cmd_ircnet_list(void) static void cmd_ircnet_add(const char *data) { - char *params, *args, *kicks, *msgs, *modes, *whois; - char *cmdspeed, *cmdmax, *nick, *user, *realname, *host, *autosendcmd, *name; + GHashTable *optlist; + char *name, *value; + void *free_arg; IRCNET_REC *rec; - args = "kicks msgs modes whois cmdspeed cmdmax nick user realname host autosendcmd"; - params = cmd_get_params(data, 13 | PARAM_FLAG_MULTIARGS, &args, - &kicks, &msgs, &modes, &whois, &cmdspeed, - &cmdmax, &nick, &user, &realname, &host, - &autosendcmd, &name); + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, + "ircnet add", &optlist, &name)) + return; if (*name == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); rec = ircnet_find(name); @@ -95,37 +94,50 @@ static void cmd_ircnet_add(const char *data) rec = g_new0(IRCNET_REC, 1); rec->name = g_strdup(name); } else { - if (stristr(args, "-nick")) g_free_and_null(rec->nick); - if (stristr(args, "-user")) g_free_and_null(rec->username); - if (stristr(args, "-realname")) g_free_and_null(rec->realname); - if (stristr(args, "-host")) { + if (g_hash_table_lookup(optlist, "nick")) g_free_and_null(rec->nick); + if (g_hash_table_lookup(optlist, "user")) g_free_and_null(rec->username); + if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname); + if (g_hash_table_lookup(optlist, "host")) { g_free_and_null(rec->own_host); rec->own_ip = NULL; } - if (stristr(args, "-autosendcmd")) g_free_and_null(rec->autosendcmd); + if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd); } - if (stristr(args, "-kicks")) rec->max_kicks = atoi(kicks); - if (stristr(args, "-msgs")) rec->max_msgs = atoi(msgs); - if (stristr(args, "-modes")) rec->max_modes = atoi(modes); - if (stristr(args, "-whois")) rec->max_whois = atoi(whois); - - if (stristr(args, "-cmdspeed")) rec->cmd_queue_speed = atoi(cmdspeed); - if (stristr(args, "-cmdmax")) rec->max_cmds_at_once = atoi(cmdmax); - - if (*nick != '\0') rec->nick = g_strdup(nick); - if (*user != '\0') rec->username = g_strdup(user); - if (*realname != '\0') rec->realname = g_strdup(realname); - if (*host != '\0') { - rec->own_host = g_strdup(host); + value = g_hash_table_lookup(optlist, "kicks"); + if (value != NULL) rec->max_kicks = atoi(value); + value = g_hash_table_lookup(optlist, "msgs"); + if (value != NULL) rec->max_msgs = atoi(value); + value = g_hash_table_lookup(optlist, "modes"); + if (value != NULL) rec->max_modes = atoi(value); + value = g_hash_table_lookup(optlist, "whois"); + if (value != NULL) rec->max_whois = atoi(value); + + value = g_hash_table_lookup(optlist, "cmdspeed"); + if (value != NULL) rec->cmd_queue_speed = atoi(value); + value = g_hash_table_lookup(optlist, "cmdmax"); + if (value != NULL) rec->max_cmds_at_once = atoi(value); + + value = g_hash_table_lookup(optlist, "nick"); + if (value != NULL && *value != '\0') rec->nick = g_strdup(value); + value = g_hash_table_lookup(optlist, "user"); + if (value != NULL && *value != '\0') rec->username = g_strdup(value); + value = g_hash_table_lookup(optlist, "realname"); + if (value != NULL && *value != '\0') rec->realname = g_strdup(value); + + value = g_hash_table_lookup(optlist, "host"); + if (value != NULL && *value != '\0') { + rec->own_host = g_strdup(value); rec->own_ip = NULL; } - if (*autosendcmd != '\0') rec->autosendcmd = g_strdup(autosendcmd); + + value = g_hash_table_lookup(optlist, "autosendcmd"); + if (value != NULL && *value != '\0') rec->autosendcmd = g_strdup(value); ircnet_create(rec); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_IRCNET_ADDED, name); - g_free(params); + cmd_params_free(free_arg); } static void cmd_ircnet_remove(const char *data) @@ -149,6 +161,8 @@ void fe_ircnet_init(void) command_bind("ircnet ", NULL, (SIGNAL_FUNC) cmd_ircnet_list); command_bind("ircnet add", NULL, (SIGNAL_FUNC) cmd_ircnet_add); command_bind("ircnet remove", NULL, (SIGNAL_FUNC) cmd_ircnet_remove); + + command_set_options("ircnet add", "-kicks -msgs -modes -whois -cmdspeed -cmdmax -nick -user -realname -host -autosendcmd"); } void fe_ircnet_deinit(void) diff --git a/src/fe-common/irc/irc-completion.c b/src/fe-common/irc/irc-completion.c index 45065aca..76f97c5c 100644 --- a/src/fe-common/irc/irc-completion.c +++ b/src/fe-common/irc/irc-completion.c @@ -167,17 +167,19 @@ static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char * static void cmd_msg(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *msg; + char *target, *msg; + void *free_arg; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) + return; if (*target != '\0' && *msg != '\0') { if (!ischannel(*target) && *target != '=' && server != NULL) add_private_msg(server, target); } - g_free(params); + cmd_params_free(free_arg); } static void sig_nick_removed(CHANNEL_REC *channel, NICK_REC *nick) diff --git a/src/fe-text/gui-textwidget.c b/src/fe-text/gui-textwidget.c index f00e2afd..6a5325d0 100644 --- a/src/fe-text/gui-textwidget.c +++ b/src/fe-text/gui-textwidget.c @@ -91,31 +91,43 @@ static gchar *gui_window_line2text(LINE_REC *line) #define LASTLOG_FLAG_WORD 0x08 #define LASTLOG_FLAG_REGEXP 0x10 -static int lastlog_parse_args(char *args, int *flags) +static int lastlog_parse_options(GHashTable *options, int *flags) { - char **arglist, **tmp; - int level; + GSList *list, *tmp; + int level, optlevel; + + /* move all keys from `options' to linked list */ + list = hashtable_get_keys(options); /* level can be specified in arguments.. */ level = 0; *flags = 0; - arglist = g_strsplit(args, " ", -1); - for (tmp = arglist; *tmp != NULL; tmp++) { - if (strcmp(*tmp, "-") == 0) + for (tmp = list; tmp != NULL; tmp = tmp->next) { + char *opt = tmp->data; + + if (strcmp(opt, "-") == 0) *flags |= LASTLOG_FLAG_NOHEADERS; - else if (g_strcasecmp(*tmp, "-new") == 0) + else if (g_strcasecmp(opt, "new") == 0) *flags |= LASTLOG_FLAG_NEW_LAST; - else if (g_strcasecmp(*tmp, "-away") == 0) + else if (g_strcasecmp(opt, "away") == 0) *flags |= LASTLOG_FLAG_NEW_AWAY; - else if (g_strcasecmp(*tmp, "-word") == 0) + else if (g_strcasecmp(opt, "word") == 0) *flags |= LASTLOG_FLAG_WORD; - else if (g_strcasecmp(*tmp, "-regexp") == 0) + else if (g_strcasecmp(opt, "regexp") == 0) *flags |= LASTLOG_FLAG_REGEXP; - else - level |= level2bits(tmp[0]+1); + else { + optlevel = level2bits(opt); + if (optlevel != 0) + level |= optlevel; + else { + signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_OPTION_UNKNOWN), opt); + level = -1; + break; + } + } } if (level == 0) level = MSGLEVEL_ALL; - g_strfreev(arglist); + g_slist_free(list); return level; } @@ -148,14 +160,19 @@ static GList *lastlog_find_startline(GList *list, int count, int start, int leve static void cmd_lastlog(const char *data) { + GHashTable *optlist; GList *startline, *list, *tmp; - char *params, *str, *args, *text, *countstr, *start; + char *str, *text, *countstr, *start; + void *free_arg; struct tm *tm; int level, flags, count; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 4 | PARAM_FLAG_OPTARGS, &args, &text, &countstr, &start); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS, + "lastlog", &optlist, &text, &countstr, &start)) + return; + if (*start == '\0' && is_numeric(text, 0)) { if (is_numeric(countstr, 0)) start = countstr; @@ -165,7 +182,12 @@ static void cmd_lastlog(const char *data) count = atoi(countstr); if (count == 0) count = -1; - level = lastlog_parse_args(args, &flags); + level = lastlog_parse_options(optlist, &flags); + if (level == -1) { + /* error in options */ + cmd_params_free(free_arg); + return; + } if ((flags & LASTLOG_FLAG_NOHEADERS) == 0) printformat(NULL, NULL, MSGLEVEL_LASTLOG, IRCTXT_LASTLOG_START); @@ -207,7 +229,7 @@ static void cmd_lastlog(const char *data) g_list_last(WINDOW_GUI(active_win)->bottom_startline); g_list_free(list); - g_free(params); + cmd_params_free(free_arg); } static void cmd_scrollback(gchar *data, SERVER_REC *server, WI_ITEM_REC *item) @@ -254,10 +276,12 @@ static void scrollback_goto_pos(WINDOW_REC *window, GList *pos) static void cmd_scrollback_goto(gchar *data) { GList *pos; - gchar *params, *arg1, *arg2; + gchar *arg1, *arg2; + void *free_arg; gint lines; - params = cmd_get_params(data, 2, &arg1, &arg2); + if (!cmd_get_params(data, &free_arg, 2, &arg1, &arg2)) + return; if (*arg2 == '\0' && (*arg1 == '-' || *arg1 == '+')) { /* go forward/backward n lines */ @@ -322,7 +346,7 @@ static void cmd_scrollback_goto(gchar *data) if (stamp > time(NULL)) { /* we're still looking into future, don't bother checking */ - g_free(params); + cmd_params_free(free_arg); return; } @@ -338,7 +362,7 @@ static void cmd_scrollback_goto(gchar *data) } } } - g_free(params); + cmd_params_free(free_arg); } static void cmd_scrollback_home(gchar *data) @@ -398,6 +422,7 @@ void gui_textwidget_init(void) command_bind("scrollback goto", NULL, (SIGNAL_FUNC) cmd_scrollback_goto); command_bind("scrollback home", NULL, (SIGNAL_FUNC) cmd_scrollback_home); command_bind("scrollback end", NULL, (SIGNAL_FUNC) cmd_scrollback_end); + command_set_options("lastlog", "new away word regexp"); signal_add("away mode changed", (SIGNAL_FUNC) sig_away_changed); } diff --git a/src/irc/bot/botnet-connection.c b/src/irc/bot/botnet-connection.c index 387cce45..988a9b5c 100644 --- a/src/irc/bot/botnet-connection.c +++ b/src/irc/bot/botnet-connection.c @@ -480,14 +480,16 @@ static BOT_REC *bot_add(BOTNET_REC *botnet, const char *nick, const char *parent static void botnet_event_botinfo(BOT_REC *bot, const char *data, const char *sender) { - char *params, *nick, *parent, *priority; + char *nick, *parent, *priority; + void *free_arg; BOT_REC *rec; /*str = g_strdup_printf("BOTINFO %s", data); botnet_broadcast(bot->botnet, bot, sender, str); g_free(str);*/ - params = cmd_get_params(data, 3, &nick, &parent, &priority); + if (!cmd_get_params(data, &free_arg, 3, &nick, &parent, &priority)) + return; if (*parent == '-' && parent[1] == '\0') parent = NULL; @@ -503,7 +505,7 @@ static void botnet_event_botinfo(BOT_REC *bot, const char *data, const char *sen if (rec != NULL) { rec->priority = atoi(priority); } - g_free(params); + cmd_params_free(free_arg); } static void botnet_event_botquit(BOT_REC *bot, const char *data) diff --git a/src/irc/bot/botnet-users.c b/src/irc/bot/botnet-users.c index fda58723..3b366ac6 100644 --- a/src/irc/bot/botnet-users.c +++ b/src/irc/bot/botnet-users.c @@ -108,81 +108,94 @@ void botcmd_user_set_password(USER_REC *user, const char *password) static void botnet_event_user_add(BOT_REC *bot, const char *data, const char *sender) { - char *params, *nick; + char *nick; + void *free_arg; + + if (!cmd_get_params(data, &free_arg, 1, &nick)) + return; - params = cmd_get_params(data, 1, &nick); botuser_add(nick); - g_free(params); + cmd_params_free(free_arg); } static void botnet_event_user_flags(BOT_REC *bot, const char *data, const char *sender) { USER_REC *user; - char *params, *nick, *flags; + char *nick, *flags; + void *free_arg; - params = cmd_get_params(data, 2, &nick, &flags); + if (!cmd_get_params(data, &free_arg, 2, &nick, &flags)) + return; user = botuser_find(nick, NULL); if (user == NULL) user = botuser_add(nick); botuser_set_flags(user, botuser_flags2value(flags)); - g_free(params); + cmd_params_free(free_arg); } static void botnet_event_user_chan_flags(BOT_REC *bot, const char *data, const char *sender) { USER_REC *user; - char *params, *nick, *channel, *flags; + char *nick, *channel, *flags; + void *free_arg; - params = cmd_get_params(data, 3, &nick, &channel, &flags); + if (!cmd_get_params(data, &free_arg, 3, &nick, &channel, &flags)) + return; user = botuser_find(nick, NULL); if (user == NULL) user = botuser_add(nick); botuser_set_channel_flags(user, channel, botuser_flags2value(flags)); - g_free(params); + cmd_params_free(free_arg); } static void botnet_event_user_add_mask(BOT_REC *bot, const char *data, const char *sender) { USER_REC *user; - char *params, *nick, *mask; + char *nick, *mask; + void *free_arg; - params = cmd_get_params(data, 2, &nick, &mask); + if (!cmd_get_params(data, &free_arg, 2, &nick, &mask)) + return; user = botuser_find(nick, NULL); if (user == NULL) user = botuser_add(nick); botuser_add_mask(user, mask); - g_free(params); + cmd_params_free(free_arg); } static void botnet_event_user_mask_notflags(BOT_REC *bot, const char *data, const char *sender) { USER_REC *user; - char *params, *nick, *mask, *not_flags; + char *nick, *mask, *not_flags; + void *free_arg; - params = cmd_get_params(data, 3, &nick, &mask, ¬_flags); + if (!cmd_get_params(data, &free_arg, 3, &nick, &mask, ¬_flags)) + return; user = botuser_find(nick, NULL); if (user == NULL) user = botuser_add(nick); botuser_set_mask_notflags(user, mask, botuser_flags2value(not_flags)); - g_free(params); + cmd_params_free(free_arg); } static void botnet_event_user_pass(BOT_REC *bot, const char *data, const char *sender) { USER_REC *user; - char *params, *nick, *pass; + char *nick, *pass; + void *free_arg; - params = cmd_get_params(data, 2, &nick, &pass); + if (!cmd_get_params(data, &free_arg, 2, &nick, &pass)) + return; user = botuser_find(nick, NULL); if (user == NULL) user = botuser_add(nick); botuser_set_password(user, pass); - g_free(params); + cmd_params_free(free_arg); } void botnet_users_init(void) diff --git a/src/irc/bot/botnet.c b/src/irc/bot/botnet.c index 4f74a867..190481d1 100644 --- a/src/irc/bot/botnet.c +++ b/src/irc/bot/botnet.c @@ -508,13 +508,15 @@ static void botnet_destroy(BOTNET_REC *botnet) static void botnet_event(BOT_REC *bot, const char *data) { - char *params, *source, *target, *command, *args, *event; + char *source, *target, *command, *args, *event; + void *free_arg; if (!bot->connected) return; - params = cmd_get_params(data, 4 | PARAM_FLAG_GETREST, - &source, &target, &command, &args); + if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_GETREST, + &source, &target, &command, &args)) + return; if (*target == '-' && target[1] == '\0') target = NULL; @@ -524,23 +526,25 @@ static void botnet_event(BOT_REC *bot, const char *data) signal_emit(event, 4, bot, args, source, target); g_free(event); - g_free(params); + cmd_params_free(free_arg); } /* broadcast the signal forward */ static void botnet_event_broadcast(BOT_REC *bot, const char *data) { - char *params, *source, *target, *command; + char *source, *target, *command; + void *free_arg; if (!bot->connected) return; - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, - &source, &target, &command); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, + &source, &target, &command)) + return; if (g_strcasecmp(target, bot->botnet->nick) == 0) { /* message was for us */ - g_free(params); + cmd_params_free(free_arg); return; } @@ -552,7 +556,7 @@ static void botnet_event_broadcast(BOT_REC *bot, const char *data) botnet_send_cmd(bot->botnet, source, target, command); } - g_free(params); + cmd_params_free(free_arg); } static void botnet_event_master(BOT_REC *bot, const char *data, const char *sender) diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c index 774587cf..914fad65 100644 --- a/src/irc/core/bans.c +++ b/src/irc/core/bans.c @@ -167,14 +167,15 @@ void ban_remove(CHANNEL_REC *channel, const char *bans) static void command_set_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item, int set) { CHANNEL_REC *chanrec; - char *params, *channel, *nicks; + char *channel, *nicks; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, - item, &channel, &nicks); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, + item, &channel, &nicks)) return; if (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED); if (*nicks == '\0') { if (strcmp(data, "*") != 0) @@ -192,7 +193,7 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC else ban_remove(chanrec, nicks); - g_free(params); + cmd_params_free(free_arg); } static void cmd_bantype(const char *data) diff --git a/src/irc/core/channels-query.c b/src/irc/core/channels-query.c index 0876f0bd..95ab9ecd 100644 --- a/src/irc/core/channels-query.c +++ b/src/irc/core/channels-query.c @@ -181,8 +181,8 @@ static void channel_send_query(IRC_SERVER_REC *server, int query) chans = rec->queries[query]; - chanstr_commas = gslist_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), ","); - chanstr_spaces = gslist_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), " "); + chanstr_commas = gslistptr_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), ","); + chanstr_spaces = gslistptr_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), " "); chanstr = g_strconcat(chanstr_commas, " ", chanstr_spaces, NULL); g_free(chanstr_spaces); diff --git a/src/irc/core/channels.c b/src/irc/core/channels.c index 6943952e..1048b202 100644 --- a/src/irc/core/channels.c +++ b/src/irc/core/channels.c @@ -162,15 +162,17 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) SETUP_CHANNEL_REC *schannel; CHANNEL_REC *chanrec; GString *outchans, *outkeys; - char *params, *channels, *keys, *key; + char *channels, *keys, *key; char **chanlist, **keylist, **tmp, **tmpkey, *channel; + void *free_arg; int use_keys; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &channels, &keys); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channels, &keys)) + return; if (*channels == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); chanlist = g_strsplit(channels, ",", -1); @@ -221,7 +223,7 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) g_strfreev(chanlist); g_strfreev(keylist); - g_free(params); + cmd_params_free(free_arg); } void channels_init(void) diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index a344931b..edc0dd7e 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -49,27 +49,34 @@ static IRC_SERVER_REC *connect_server(const char *data) { IRC_SERVER_CONNECT_REC *conn; IRC_SERVER_REC *server; - char *params, *args, *ircnet, *host, *addr, *portstr, *password, *nick; + GHashTable *optlist; + char *addr, *portstr, *password, *nick, *ircnet, *host; + void *free_arg; g_return_val_if_fail(data != NULL, NULL); - args = "ircnet host"; - params = cmd_get_params(data, 7 | PARAM_FLAG_MULTIARGS, - &args, &ircnet, &host, &addr, - &portstr, &password, &nick); + if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_OPTIONS, + "connect", &optlist, &addr, &portstr, &password, &nick)) + return NULL; if (*addr == '+') addr++; - if (*addr == '\0') return NULL; + if (*addr == '\0') { + signal_emit("error command", 1, GINT_TO_POINTER(CMDERR_NOT_ENOUGH_PARAMS)); + cmd_params_free(free_arg); + return NULL; + } if (strcmp(password, "-") == 0) *password = '\0'; /* connect to server */ conn = irc_server_create_conn(addr, atoi(portstr), password, nick); - if (*ircnet != '\0') { + ircnet = g_hash_table_lookup(optlist, "ircnet"); + if (ircnet != NULL && *ircnet != '\0') { g_free_not_null(conn->ircnet); conn->ircnet = g_strdup(ircnet); } - if (*host != '\0') { + host = g_hash_table_lookup(optlist, "host"); + if (host != NULL && *host != '\0') { IPADDR ip; if (net_gethostbyname(host, &ip) == 0) { @@ -80,7 +87,7 @@ static IRC_SERVER_REC *connect_server(const char *data) } server = irc_server_connect(conn); - g_free(params); + cmd_params_free(free_arg); return server; } @@ -93,14 +100,16 @@ static void cmd_connect(const char *data) static void cmd_disconnect(const char *data, IRC_SERVER_REC *server) { IRC_SERVER_REC *ircserver; - char *params, *tag, *msg; + char *tag, *msg; + void *free_arg; g_return_if_fail(data != NULL); if (g_strncasecmp(data, "RECON-", 6) == 0) return; /* remove reconnection, handle in server-reconnect.c */ - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &tag, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg)) + return; if (*tag != '\0' && strcmp(tag, "*") != 0) server = (IRC_SERVER_REC *) server_find_tag(tag); @@ -120,22 +129,24 @@ static void cmd_disconnect(const char *data, IRC_SERVER_REC *server) irc_send_cmdv(ircserver, "QUIT :%s", msg); } - g_free(params); + cmd_params_free(free_arg); server_disconnect((SERVER_REC *) server); } static void cmd_server(const char *data, IRC_SERVER_REC *server) { - char *params, *args, *ircnetarg, *hostarg, *addr; - char *channels, *away_reason, *usermode, *ircnet; + GHashTable *optlist; + char *addr, *channels, *away_reason, *usermode, *ircnet; + void *free_arg; int no_old_server; g_return_if_fail(data != NULL); - args = "ircnet host"; - params = cmd_get_params(data, 4 | PARAM_FLAG_MULTIARGS, - &args, &ircnetarg, &hostarg, &addr); + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, + "connect", &optlist, &addr)) + return; + if (*addr == '\0' || strcmp(addr, "+") == 0) cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -167,7 +178,7 @@ static void cmd_server(const char *data, IRC_SERVER_REC *server) server->connrec->away_reason = away_reason; } g_free_not_null(ircnet); - g_free(params); + cmd_params_free(free_arg); } static void cmd_quit(const char *data) @@ -195,12 +206,14 @@ static void cmd_quit(const char *data) static void cmd_msg(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *target, *msg; + char *target, *msg; + void *free_arg; int free_ret; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) + return; if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (server == NULL || !server->connected || !irc_server_check(server)) @@ -219,35 +232,39 @@ static void cmd_msg(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) if (free_ret && target != NULL) g_free(target); - g_free(params); + cmd_params_free(free_arg); } static void cmd_notice(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *msg; + char *target, *msg; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) + return; if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); g_string_sprintf(tmpstr, "NOTICE %s :%s", target, msg); irc_send_cmd_split(server, tmpstr->str, 2, server->max_msgs_in_cmd); - g_free(params); + cmd_params_free(free_arg); } static void cmd_ctcp(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *ctcpcmd, *ctcpdata; + char *target, *ctcpcmd, *ctcpdata; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) + return; if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); g_strup(ctcpcmd); @@ -257,61 +274,79 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server) g_string_sprintf(tmpstr, "PRIVMSG %s :\001%s %s\001", target, ctcpcmd, ctcpdata); irc_send_cmd_split(server, tmpstr->str, 2, server->max_msgs_in_cmd); - g_free(params); + cmd_params_free(free_arg); } static void cmd_nctcp(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *ctcpcmd, *ctcpdata; + char *target, *ctcpcmd, *ctcpdata; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) + return; if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); g_strup(ctcpcmd); g_string_sprintf(tmpstr, "NOTICE %s :\001%s %s\001", target, ctcpcmd, ctcpdata); irc_send_cmd_split(server, tmpstr->str, 2, server->max_msgs_in_cmd); - g_free(params); + cmd_params_free(free_arg); } static void cmd_join(const char *data, IRC_SERVER_REC *server) { - char *params, *args, *channels; + GHashTable *optlist; + GSList *list; + char *channels; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST, &args, &channels); + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS | + PARAM_FLAG_GETREST, "join", &optlist, &channels)) + return; - if (stristr(args, "-invite")) { + if (g_hash_table_lookup(optlist, "-invite")) { if (server->last_invite != NULL) channels_join(server, server->last_invite, FALSE); } else { - if (*args != '\0') { - server = (IRC_SERVER_REC *) server_find_tag(args+1); - if (server == NULL) cmd_param_error(CMDERR_NOT_CONNECTED); + /* - */ + list = hashtable_get_keys(optlist); + if (list != NULL) { + server = (IRC_SERVER_REC *) server_find_tag(list->data); + + if (server == NULL) { + /* unknown option (not server tag) */ + signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_OPTION_UNKNOWN), list->data); + signal_stop(); + } + g_slist_free(list); } - channels_join(server, channels, FALSE); + + if (server != NULL) channels_join(server, channels, FALSE); } - g_free(params); + cmd_params_free(free_arg); } static void cmd_part(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *channame, *msg; CHANNEL_REC *chanrec; + char *channame, *msg; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg)) + return; if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); chanrec = channel_find(server, channame); @@ -320,19 +355,21 @@ static void cmd_part(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) irc_send_cmdv(server, *msg == '\0' ? "PART %s" : "PART %s :%s", channame, msg); - g_free(params); + cmd_params_free(free_arg); } static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *channame, *nicks, *reason; + char *channame, *nicks, *reason; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, - item, &channame, &nicks, &reason); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, + item, &channame, &nicks, &reason)) + return; if (*channame == '\0' || *nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (!ischannel(*channame)) cmd_param_error(CMDERR_NOT_JOINED); @@ -340,36 +377,42 @@ static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) g_string_sprintf(tmpstr, "KICK %s %s :%s", channame, nicks, reason); irc_send_cmd_split(server, tmpstr->str, 3, server->max_kicks_in_cmd); - g_free(params); + cmd_params_free(free_arg); } static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *args, *channame, *topic; + GHashTable *optlist; + char *channame, *topic; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_OPTCHAN | - PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST, - item, &args, &channame, &topic); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTCHAN | + PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, + item, "topic", &optlist, &channame, &topic)) + return; - irc_send_cmdv(server, *topic == '\0' && strstr(args, "-d") == NULL ? + irc_send_cmdv(server, *topic == '\0' && g_hash_table_lookup(optlist, "-d") == NULL ? "TOPIC %s" : "TOPIC %s :%s", channame, topic); - g_free(params); + cmd_params_free(free_arg); } static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *nick, *channame; + char *nick, *channame; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2, &nick, &channame); + if (!cmd_get_params(data, &free_arg, 2, &nick, &channame)) + return; + if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*channame == '\0' || strcmp(channame, "*") == 0) { if (!irc_item_channel(item)) @@ -379,24 +422,28 @@ static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *ite } irc_send_cmdv(server, "INVITE %s %s", nick, channame); - g_free(params); + cmd_params_free(free_arg); } static void cmd_list(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *args, *str; + GHashTable *optlist; + char *str; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST, &args, &str); + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_GETREST, &optlist, &str)) + return; - if (*str == '\0' && stristr(args, "-yes") == NULL) + if (*str == '\0' && g_hash_table_lookup(optlist, "-yes") == NULL) cmd_param_error(CMDERR_NOT_GOOD_IDEA); irc_send_cmdv(server, "LIST %s", str); - g_free(params); + cmd_params_free(free_arg); /* add default redirection */ server_redirect_default((SERVER_REC *) server, "bogus command list"); @@ -404,13 +451,15 @@ static void cmd_list(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) static void cmd_who(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *channel, *args, *rest; + char *channel, *rest; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST, &args, &channel, &rest); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &channel, &rest)) + return; if (strcmp(channel, "*") == 0 || *channel == '\0') { if (!irc_item_channel(item)) @@ -425,7 +474,7 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) irc_send_cmdv(server, *rest == '\0' ? "WHO %s" : "WHO %s %s", channel, rest); - g_free(params); + cmd_params_free(free_arg); /* add default redirection */ server_redirect_default((SERVER_REC *) server, "bogus command who"); @@ -473,17 +522,20 @@ static char *get_redirect_nicklist(const char *nicks, int *free) static void cmd_whois(const char *data, IRC_SERVER_REC *server) { - char *params, *qserver, *query; + char *qserver, *query; + void *free_arg; int free_nick; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2, &qserver, &query); + if (!cmd_get_params(data, &free_arg, 2, &qserver, &query)) + return; + if (*query == '\0') { - g_free(params); - params = cmd_get_params(data, 1, &query); + cmd_params_free(free_arg); + if (!cmd_get_params(data, &free_arg, 1, &query)) return; qserver = ""; } if (*query == '\0') query = server->nick; @@ -505,7 +557,7 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server) "event 311", "whois event", 1, "event 401", "whois not found", 1, NULL); if (free_nick) g_free(query); - g_free(params); + cmd_params_free(free_arg); } static void event_whois(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) @@ -539,14 +591,16 @@ static void event_whowas(const char *data, IRC_SERVER_REC *server, const char *n static void cmd_whowas(const char *data, IRC_SERVER_REC *server) { - char *params, *nicks, *count; + char *nicks, *count; + void *free_arg; int free_nick; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2, &nicks, &count); + if (!cmd_get_params(data, &free_arg, 2, &nicks, &count)) + return; if (*nicks == '\0') nicks = server->nick; server->whowas_found = FALSE; @@ -558,7 +612,7 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server) "event 369", "event 369", 1, "event 314", "whowas event", 1, NULL); if (free_nick) g_free(nicks); - g_free(params); + cmd_params_free(free_arg); } static void cmd_ping(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) @@ -594,20 +648,23 @@ static void server_send_away(IRC_SERVER_REC *server, const char *reason) static void cmd_away(const char *data, IRC_SERVER_REC *server) { - char *params, *args, *reason; + GHashTable *optlist; + char *reason; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_OPTARGS | PARAM_FLAG_GETREST, &args, &reason); + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_GETREST, "away", &optlist, &reason)) return; - if (stristr(args, "-one")) + if (g_hash_table_lookup(optlist, "-one") != NULL) server_send_away(server, reason); else g_slist_foreach(servers, (GFunc) server_send_away, reason); - g_free(params); + cmd_params_free(free_arg); } static void cmd_deop(const char *data, IRC_SERVER_REC *server) @@ -646,7 +703,8 @@ static void cmd_wall_hash(gpointer key, NICK_REC *nick, GSList **nicks) static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *channame, *msg, *args; + char *channame, *msg, *args; + void *free_arg; CHANNEL_REC *chanrec; GSList *tmp, *nicks; @@ -654,7 +712,9 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | + PARAM_FLAG_GETREST, item, &channame, &msg)) + return; if (*msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); chanrec = channel_find(server, channame); @@ -677,19 +737,21 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) g_free(msg); g_slist_free(nicks); - g_free(params); + cmd_params_free(free_arg); } static void cmd_cycle(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *channame, *msg; CHANNEL_REC *chanrec; + char *channame, *msg; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN, item, &channame, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN, item, &channame, &msg)) + return; if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); chanrec = channel_find(server, channame); @@ -700,21 +762,23 @@ static void cmd_cycle(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) irc_send_cmdv(server, chanrec->key == NULL ? "JOIN %s" : "JOIN %s %s", channame, chanrec->key); - g_free(params); + cmd_params_free(free_arg); } static void cmd_kickban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *nick; + char *nick; + void *free_arg; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 1, &nick); + if (!cmd_get_params(data, &free_arg, 1, &nick)) + return; if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); signal_emit("command ban", 3, nick, server, item); signal_emit("command kick", 3, data, server, item); - g_free(params); + cmd_params_free(free_arg); } static void knockout_destroy(IRC_SERVER_REC *server, KNOCKOUT_REC *rec) @@ -760,7 +824,8 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i { KNOCKOUT_REC *rec; CHANNEL_REC *channel; - char *params, *nick, *reason, *timeoutstr, *str; + char *nick, *reason, *timeoutstr, *str; + void *free_arg; int timeleft; g_return_if_fail(data != NULL); @@ -771,11 +836,13 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i if (is_numeric(data, ' ')) { /* first argument is the timeout */ - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &timeoutstr, &nick, &reason); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &timeoutstr, &nick, &reason)) + return; timeleft = atoi(timeoutstr); } else { timeleft = 0; - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &nick, &reason); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nick, &reason)) + return; } if (timeleft == 0) timeleft = settings_get_int("knockout_time"); @@ -795,7 +862,7 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i server->knockoutlist = g_slist_append(server->knockoutlist, rec); - g_free(params); + cmd_params_free(free_arg); } /* destroy all knockouts in server */ @@ -845,16 +912,18 @@ static void command_1self(const char *data, IRC_SERVER_REC *server) static void command_2self(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *text; + char *target, *text; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &text); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text)) + return; if (*target == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); irc_send_cmdv(server, "%s %s :%s", current_command, target, text); - g_free(params); + cmd_params_free(free_arg); } static void sig_connected(IRC_SERVER_REC *server) @@ -942,6 +1011,12 @@ void irc_commands_init(void) signal_add("whois not found", (SIGNAL_FUNC) sig_whois_not_found); signal_add("whois event", (SIGNAL_FUNC) event_whois); signal_add("whowas event", (SIGNAL_FUNC) event_whowas); + + command_set_options("connect", "+ircnet +host"); + command_set_options("topic", "d"); + command_set_options("list", "yes"); + command_set_options("away", "one all"); + command_set_options("join", "invite"); } void irc_commands_deinit(void) diff --git a/src/irc/core/irc-special-vars.c b/src/irc/core/irc-special-vars.c index 09e0db11..92acd246 100644 --- a/src/irc/core/irc-special-vars.c +++ b/src/irc/core/irc-special-vars.c @@ -236,11 +236,13 @@ static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char * static void cmd_msg(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *msg; + char *target, *msg; + void *free_arg; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) + return; if (*target != '\0' && *msg != '\0' && !ischannel(*target) && isalpha(*target)) { g_free_not_null(last_sent_msg); g_free_not_null(last_sent_msg_body); @@ -248,7 +250,7 @@ static void cmd_msg(const char *data, IRC_SERVER_REC *server) last_sent_msg_body = g_strdup(msg); } - g_free(params); + cmd_params_free(free_arg); } static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address) diff --git a/src/irc/core/ircnet-setup.c b/src/irc/core/ircnet-setup.c index 57cfab1a..b3946e6a 100644 --- a/src/irc/core/ircnet-setup.c +++ b/src/irc/core/ircnet-setup.c @@ -154,11 +154,11 @@ static void read_ircnets(void) static void sig_connected(IRC_SERVER_REC *server) { IRCNET_REC *ircnet; - + if (server->connrec->ircnet == NULL) return; ircnet = ircnet_find(server->connrec->ircnet); - if (ircnet->autosendcmd) + if (ircnet != NULL && ircnet->autosendcmd) eval_special_string(ircnet->autosendcmd, "", server, NULL); } diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c index 715ad040..fcca2401 100644 --- a/src/irc/core/modes.c +++ b/src/irc/core/modes.c @@ -460,7 +460,8 @@ static void cmd_devoice(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *it static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *target, *mode; + char *target, *mode; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) @@ -468,9 +469,11 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) if (*data == '+' || *data == '-') { target = "*"; - params = mode = g_strdup(data); /* cmd_param_error() wants to free params.. */ + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_GETREST, &mode)) + return; } else { - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &mode); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &mode)) + return; } if (strcmp(target, "*") == 0) { @@ -488,7 +491,7 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) else irc_send_cmdv(server, "MODE %s %s", target, mode); - g_free(params); + cmd_params_free(free_arg); } void modes_init(void) diff --git a/src/irc/core/netsplit.c b/src/irc/core/netsplit.c index bfa40c3c..0c394055 100644 --- a/src/irc/core/netsplit.c +++ b/src/irc/core/netsplit.c @@ -187,7 +187,8 @@ NICK_REC *netsplit_find_channel(IRC_SERVER_REC *server, const char *nick, const int quitmsg_is_split(const char *msg) { - char *params, *host1, *host2, *p; + char *host1, *host2, *p; + void *free_arg; int ok; g_return_val_if_fail(msg != NULL, FALSE); @@ -202,8 +203,10 @@ int quitmsg_is_split(const char *msg) return FALSE; /* get the two hosts */ + if (!cmd_get_params(msg, &free_arg, 2 | PARAM_FLAG_NOQUOTES, &host1, &host2)) + return FALSE; + ok = FALSE; - params = cmd_get_params(msg, 2 | PARAM_FLAG_NOQUOTES, &host1, &host2); if (g_strcasecmp(host1, host2) != 0) { /* hosts can't be same.. */ /* check that domain length is 2 or 3 */ p = strrchr(host1, '.'); @@ -215,7 +218,7 @@ int quitmsg_is_split(const char *msg) } } } - g_free(params); + cmd_params_free(free_arg); return ok; } diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c index 44968ce0..afdb9d5b 100644 --- a/src/irc/dcc/dcc-chat.c +++ b/src/irc/dcc/dcc-chat.c @@ -59,7 +59,8 @@ DCC_REC *item_get_dcc(void *item) static void cmd_msg(const char *data) { DCC_REC *dcc; - char *params, *text, *target; + char *text, *target; + void *free_arg; g_return_if_fail(text != NULL); @@ -68,12 +69,13 @@ static void cmd_msg(const char *data) return; } - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &text); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text)) + return; dcc = dcc_find_item(DCC_TYPE_CHAT, ++target, NULL); if (dcc != NULL) dcc_chat_send(dcc, text); - g_free(params); + cmd_params_free(free_arg); signal_stop(); } @@ -96,9 +98,9 @@ static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) static void cmd_action(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *text; DCC_REC *dcc; - char *str; + char *target, *text, *str; + void *free_arg; g_return_if_fail(data != NULL); @@ -107,7 +109,8 @@ static void cmd_action(const char *data, IRC_SERVER_REC *server) return; } - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &text)) + return; if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL); @@ -117,25 +120,26 @@ static void cmd_action(const char *data, IRC_SERVER_REC *server) g_free(str); } - g_free(params); + cmd_params_free(free_arg); signal_stop(); } static void cmd_ctcp(const char *data, IRC_SERVER_REC *server) { - char *params, *target, *ctcpcmd, *ctcpdata; DCC_REC *dcc; - char *str; + char *target, *ctcpcmd, *ctcpdata, *str; + void *free_arg; g_return_if_fail(data != NULL); if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) + return; if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*target != '=') { /* handle only DCC CTCPs */ - g_free(params); + cmd_params_free(free_arg); return; } @@ -148,7 +152,7 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server) g_free(str); } - g_free(params); + cmd_params_free(free_arg); signal_stop(); } diff --git a/src/irc/dcc/dcc-files.c b/src/irc/dcc/dcc-files.c index e2dc732d..9a68813f 100644 --- a/src/irc/dcc/dcc-files.c +++ b/src/irc/dcc/dcc-files.c @@ -212,12 +212,14 @@ static void cmd_dcc_get(const char *data) { DCC_REC *dcc; GSList *tmp, *next; - char *params, *nick, *fname; + char *nick, *fname; + void *free_arg; int found; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &nick, &fname); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nick, &fname)) + return; if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); dcc = NULL; found = FALSE; @@ -235,7 +237,7 @@ static void cmd_dcc_get(const char *data) if (!found) signal_emit("dcc error get not found", 1, nick); - g_free(params); + cmd_params_free(free_arg); } static void dcc_resume_send(DCC_REC *dcc, int port) @@ -264,7 +266,8 @@ static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server, const char *sender, const char *sendaddr, const char *target, DCC_REC *chat) { - char *params, *type, *arg, *portstr, *sizestr; + char *type, *arg, *portstr, *sizestr; + void *free_arg; unsigned long size; int port; DCC_REC *dcc; @@ -272,8 +275,9 @@ static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server, g_return_if_fail(data != NULL); g_return_if_fail(sender != NULL); - params = cmd_get_params(data, 4 | PARAM_FLAG_NOQUOTES, - &type, &arg, &portstr, &sizestr); + if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_NOQUOTES, + &type, &arg, &portstr, &sizestr)) + return; port = atoi(portstr); size = atol(sizestr); @@ -281,7 +285,7 @@ static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server, dcc = dcc_find_by_port(sender, port); if (dcc == NULL || !is_resume_type(type) || !is_resume_ok(type, dcc) || !is_accept_ok(type, dcc)) { - g_free(params); + cmd_params_free(free_arg); return; } @@ -298,7 +302,7 @@ static void dcc_ctcp_msg(const char *data, IRC_SERVER_REC *server, dcc_get_connect(dcc); } - g_free(params); + cmd_params_free(free_arg); } static void dcc_resume_rec(DCC_REC *dcc) @@ -331,12 +335,14 @@ static void cmd_dcc_resume(const char *data) { DCC_REC *dcc; GSList *tmp; - char *params, *nick, *fname; + char *nick, *fname; + void *free_arg; int found; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &nick, &fname); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &nick, &fname)) + return; if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); dcc = NULL; found = FALSE; @@ -353,7 +359,7 @@ static void cmd_dcc_resume(const char *data) if (!found) signal_emit("dcc error get not found", 1, nick); - g_free(params); + cmd_params_free(free_arg); } /* input function: DCC SEND - we're ready to send more data */ @@ -483,7 +489,8 @@ static void dcc_send_init(DCC_REC *dcc) /* command: DCC SEND */ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - char *params, *target, *fname, *str, *ptr; + char *target, *fname, *str, *ptr; + void *free_arg; char host[MAX_IP_LEN]; int hfile, hlisten, port; long fsize; @@ -492,7 +499,8 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i g_return_if_fail(data != NULL); - params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &fname); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &fname)) + return; if (*target == '\0' || *fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); /* if we're in dcc chat, send the request via it. */ @@ -506,7 +514,7 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i if (dcc_find_item(DCC_TYPE_SEND, target, fname)) { signal_emit("dcc error send exists", 2, target, fname); - g_free(params); + cmd_params_free(free_arg); return; } @@ -525,7 +533,7 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i if (hfile == -1) { signal_emit("dcc error file not found", 2, target, fname); - g_free(params); + cmd_params_free(free_arg); return; } fsize = lseek(hfile, 0, SEEK_END); @@ -565,7 +573,7 @@ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i g_free(str); g_free(fname); - g_free(params); + cmd_params_free(free_arg); } static void read_settings(void) diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index e514c934..75dc5459 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -278,7 +278,8 @@ static void dcc_get_address(const char *str, IPADDR *ip) /* Handle incoming DCC CTCP messages */ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char *sendaddr, char *target, DCC_REC *chat) { - char *params, *type, *arg, *addrstr, *portstr, *sizestr, *str; + char *type, *arg, *addrstr, *portstr, *sizestr, *str; + void *free_arg; const char *cstr; DCC_REC *dcc; gulong size; @@ -287,8 +288,9 @@ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char g_return_if_fail(data != NULL); g_return_if_fail(sender != NULL); - params = cmd_get_params(data, 5 | PARAM_FLAG_NOQUOTES, - &type, &arg, &addrstr, &portstr, &sizestr); + if (!cmd_get_params(data, &free_arg, 5 | PARAM_FLAG_NOQUOTES, + &type, &arg, &addrstr, &portstr, &sizestr)) + return; if (sscanf(portstr, "%d", &port) != 1) port = 0; if (sscanf(sizestr, "%lu", &size) != 1) size = 0; @@ -349,20 +351,22 @@ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char break; } - g_free(params); + cmd_params_free(free_arg); } /* Handle incoming DCC CTCP replies */ static void dcc_ctcp_reply(char *data, IRC_SERVER_REC *server, char *sender, char *sendaddr) { - char *params, *cmd, *subcmd, *args; + char *cmd, *subcmd, *args; + void *free_arg; int type; DCC_REC *dcc; g_return_if_fail(data != NULL); g_return_if_fail(sender != NULL); - params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &cmd, &subcmd, &args); + if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &cmd, &subcmd, &args)) + return; if (g_strcasecmp(cmd, "REJECT") == 0) { @@ -380,7 +384,7 @@ static void dcc_ctcp_reply(char *data, IRC_SERVER_REC *server, char *sender, cha signal_emit("dcc unknown reply", 3, data, sender, sendaddr); } - g_free(params); + cmd_params_free(free_arg); } static void dcc_reject(DCC_REC *dcc, IRC_SERVER_REC *server) @@ -409,20 +413,22 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server) { DCC_REC *dcc; GSList *tmp, *next; - char *params, *type, *nick, *arg; + char *type, *nick, *arg; + void *free_arg; gboolean found; int itype; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 3, &type, &nick, &arg); + if (!cmd_get_params(data, &free_arg, 3, &type, &nick, &arg)) + return; g_strup(type); itype = dcc_str2type(type); if (itype == 0) { signal_emit("dcc error unknown type", 1, type); - g_free(params); + cmd_params_free(free_arg); return; } @@ -442,7 +448,7 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server) if (!found) signal_emit("dcc error close not found", 3, type, nick, arg); - g_free(params); + cmd_params_free(free_arg); } static void cmd_dcc(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) diff --git a/src/irc/notifylist/notify-commands.c b/src/irc/notifylist/notify-commands.c index af022dcd..0bef6d23 100644 --- a/src/irc/notifylist/notify-commands.c +++ b/src/irc/notifylist/notify-commands.c @@ -30,41 +30,47 @@ static void cmd_notify(gchar *data) { - char *params, *mask, *ircnets, *args, *idletime; + GHashTable *optlist; + char *mask, *ircnets, *idletime; + void *free_arg; int away_check, idle_check_time; g_return_if_fail(data != NULL); - args = "@idle"; - params = cmd_get_params(data, 4 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST, &args, &idletime, &mask, &ircnets); + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, + "notify", &optlist, &mask, &ircnets)) + return; if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - if (stristr(args, "-idle") == NULL) + idletime = g_hash_table_lookup(optlist, "idle"); + if (idletime == NULL) idle_check_time = 0; else { idle_check_time = is_numeric(idletime, 0) ? (atoi(idletime)*60) : (settings_get_int("notify_idle_time")*60); } - away_check = stristr(args, "-away") != NULL; + away_check = g_hash_table_lookup(optlist, "away") != NULL; notifylist_remove(mask); notifylist_add(mask, ircnets, away_check, idle_check_time); - g_free(params); + cmd_params_free(free_arg); } static void cmd_unnotify(const char *data) { - char *params, *mask; + char *mask; + void *free_arg; g_return_if_fail(data != NULL); - params = cmd_get_params(data, 1, &mask); + if (!cmd_get_params(data, &free_arg, 1, &mask)) + return; if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); notifylist_remove(mask); - g_free(params); + cmd_params_free(free_arg); } void notifylist_commands_init(void) @@ -72,6 +78,8 @@ void notifylist_commands_init(void) settings_add_int("misc", "notify_idle_time", DEFAULT_NOTIFY_IDLE_TIME); command_bind("notify", NULL, (SIGNAL_FUNC) cmd_notify); command_bind("unnotify", NULL, (SIGNAL_FUNC) cmd_unnotify); + + command_set_options("notify", "@idle away"); } void notifylist_commands_deinit(void) -- cgit v1.2.3