diff options
author | dequis <dx@dxzone.com.ar> | 2014-07-24 00:51:07 -0300 |
---|---|---|
committer | dequis <dx@dxzone.com.ar> | 2014-07-24 00:51:07 -0300 |
commit | 269580c6302a677e07176494bd314c7e2a8f488f (patch) | |
tree | 393145104686ce5468d558c29a451a19677bf91d | |
parent | 1783ab6964c9a8ffc3488bb5243f0b15858f4e74 (diff) |
Add limit param to split_command_parts(), fix twitter quotes bug
Only took me a few months to write. I even added a test case.
-rw-r--r-- | irc_commands.c | 2 | ||||
-rw-r--r-- | lib/misc.c | 9 | ||||
-rw-r--r-- | lib/misc.h | 2 | ||||
-rw-r--r-- | protocols/twitter/twitter.c | 4 | ||||
-rw-r--r-- | root_commands.c | 2 | ||||
-rw-r--r-- | tests/check_util.c | 45 |
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 ) @@ -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 ) @@ -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; } |