aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--irc_commands.c2
-rw-r--r--lib/misc.c9
-rw-r--r--lib/misc.h2
-rw-r--r--protocols/twitter/twitter.c4
-rw-r--r--root_commands.c2
-rw-r--r--tests/check_util.c45
6 files changed, 57 insertions, 7 deletions
diff --git a/irc_commands.c b/irc_commands.c
index 19930121..73b781fc 100644
--- a/irc_commands.c
+++ b/irc_commands.c
@@ -364,7 +364,7 @@ static void irc_cmd_privmsg( irc_t *irc, char **cmd )
if( cmd[2][strlen(cmd[2])-1] == '\001' )
cmd[2][strlen(cmd[2])-1] = '\0';
- ctcp = split_command_parts( cmd[2] + 1 );
+ ctcp = split_command_parts( cmd[2] + 1, 0 );
iu->f->ctcp( iu, ctcp );
}
else if( iu->f->privmsg )
diff --git a/lib/misc.c b/lib/misc.c
index 49c4aa5d..2506e291 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -681,7 +681,7 @@ int md5_verify_password( char *password, char *hash )
/* Split commands (root-style, *not* IRC-style). Handles "quoting of"
white\ space in 'various ways'. Returns a NULL-terminated static
char** so watch out with nested use! Definitely not thread-safe. */
-char **split_command_parts( char *command )
+char **split_command_parts( char *command, int limit )
{
static char *cmd[IRC_MAX_ARGS+1];
char *s, q = 0;
@@ -691,11 +691,12 @@ char **split_command_parts( char *command )
cmd[0] = command;
k = 1;
for( s = command; *s && k < IRC_MAX_ARGS; s ++ )
+ {
if( *s == ' ' && !q )
{
*s = 0;
while( *++s == ' ' );
- if( *s == '"' || *s == '\'' )
+ if( k != limit && (*s == '"' || *s == '\'') )
{
q = *s;
s ++;
@@ -703,6 +704,9 @@ char **split_command_parts( char *command )
if( *s )
{
cmd[k++] = s;
+ if (limit && k > limit) {
+ break;
+ }
s --;
}
else
@@ -721,6 +725,7 @@ char **split_command_parts( char *command )
{
q = *s = 0;
}
+ }
/* Full zero-padding for easier argc checking. */
while( k <= IRC_MAX_ARGS )
diff --git a/lib/misc.h b/lib/misc.h
index 059c8231..674a61b6 100644
--- a/lib/misc.h
+++ b/lib/misc.h
@@ -66,7 +66,7 @@ G_MODULE_EXPORT void srv_free( struct ns_srv_reply **srv );
G_MODULE_EXPORT char *word_wrap( const char *msg, int line_len );
G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl );
G_MODULE_EXPORT int md5_verify_password( char *password, char *hash );
-G_MODULE_EXPORT char **split_command_parts( char *command );
+G_MODULE_EXPORT char **split_command_parts( char *command, int limit );
G_MODULE_EXPORT char *get_rfc822_header( const char *text, const char *header, int len );
#endif
diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c
index 70e11067..5aefc008 100644
--- a/protocols/twitter/twitter.c
+++ b/protocols/twitter/twitter.c
@@ -601,7 +601,7 @@ static void twitter_handle_command(struct im_connection *ic, char *message)
bee_user_t *bu = NULL;
cmds = g_strdup(message);
- cmd = split_command_parts(cmds);
+ cmd = split_command_parts(cmds, 2);
if (cmd[0] == NULL) {
goto eof;
@@ -661,7 +661,7 @@ static void twitter_handle_command(struct im_connection *ic, char *message)
"post any statuses recently", cmd[1]);
goto eof;
}
- message = new = g_strdup_printf("@%s %s", bu->handle, message + (cmd[2] - cmd[0]));
+ message = new = g_strdup_printf("@%s %s", bu->handle, cmd[2]);
in_reply_to = id;
allow_post = TRUE;
} else if (g_strcasecmp(cmd[0], "post") == 0) {
diff --git a/root_commands.c b/root_commands.c
index 2c153f0e..ca40323f 100644
--- a/root_commands.c
+++ b/root_commands.c
@@ -31,7 +31,7 @@
void root_command_string( irc_t *irc, char *command )
{
- root_command( irc, split_command_parts( command ) );
+ root_command( irc, split_command_parts( command, 0 ) );
}
#define MIN_ARGS( x, y... ) \
diff --git a/tests/check_util.c b/tests/check_util.c
index c323241e..dc73d644 100644
--- a/tests/check_util.c
+++ b/tests/check_util.c
@@ -168,6 +168,50 @@ START_TEST(test_http_encode)
fail_unless( strcmp( s, "ee%C3%ABee%21%21..." ) == 0 );
END_TEST
+struct {
+ int limit;
+ char *command;
+ char *expected[IRC_MAX_ARGS+1];
+} split_tests[] = {
+ {
+ 0, "account add etc \"user name with spaces\" 'pass\\ word'",
+ {"account", "add", "etc", "user name with spaces", "pass\\ word", NULL},
+ },
+ {
+ 0, "channel set group Close\\ friends",
+ {"channel", "set", "group", "Close friends", NULL},
+ },
+ {
+ 2, "reply wilmer \"testing in C is a PITA\", you said.",
+ {"reply", "wilmer", "\"testing in C is a PITA\", you said.", NULL},
+ },
+ {
+ 4, "one space two spaces limit limit",
+ {"one", "space", "two", "spaces", "limit limit", NULL},
+ },
+ {
+ 0, NULL,
+ {NULL}
+ },
+};
+
+START_TEST(test_split_command_parts)
+ int i;
+ for (i = 0; split_tests[i].command; i++) {
+ char *cmd = g_strdup(split_tests[i].command);
+ char **split = split_command_parts(cmd, split_tests[i].limit);
+ char **expected = split_tests[i].expected;
+
+ int j;
+ for (j = 0; split[j] && expected[j]; j++) {
+ fail_unless (strcmp(split[j], expected[j]) == 0,
+ "(%d) split_command_parts broken: split(\"%s\")[%d] -> %s (expected: %s)",
+ i, split_tests[i].command, j, split[j], expected[j]);
+ }
+ g_free(cmd);
+ }
+END_TEST
+
Suite *util_suite (void)
{
Suite *s = suite_create("Util");
@@ -182,5 +226,6 @@ Suite *util_suite (void)
tcase_add_test (tc_core, test_set_url_username_pwd);
tcase_add_test (tc_core, test_word_wrap);
tcase_add_test (tc_core, test_http_encode);
+ tcase_add_test (tc_core, test_split_command_parts);
return s;
}