struct t_hashtable * irc_message_split (struct t_irc_server *server, const char *message) { struct t_hashtable *hashtable; char **argv, **argv_eol, *tags, *host, *command, *arguments, target[512]; char *pos; int split_ok, argc, index_args, max_length_nick, max_length_host; split_ok = 0; tags = NULL; host = NULL; command = NULL; arguments = NULL; index_args = 0; argv = NULL; argv_eol = NULL; /* debug message */ if (weechat_irc_plugin->debug >= 2) weechat_printf (NULL, "irc_message_split: message='%s'", message); hashtable = weechat_hashtable_new (32, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING, NULL, NULL); if (!hashtable) return NULL; if (!message || !message[0]) goto end; if (message[0] == '@') { pos = strchr (message, ' '); if (pos) { tags = weechat_strndup (message, pos - message + 1); message = pos + 1; } } argv = weechat_string_split (message, " ", 0, 0, &argc); argv_eol = weechat_string_split (message, " ", 2, 0, NULL); if (argc < 2) goto end; if (argv[0][0] == ':') { if (argc < 3) goto end; host = argv[0]; command = argv[1]; arguments = argv_eol[2]; index_args = 2; } else { command = argv[0]; arguments = argv_eol[1]; index_args = 1; } max_length_nick = (server && (server->nick_max_length > 0)) ? server->nick_max_length : 16; max_length_host = 1 + /* ":" */ max_length_nick + /* nick */ 1 + /* "!" */ 63 + /* host */ 1; /* " " */ if ((weechat_strcasecmp (command, "ison") == 0) || (weechat_strcasecmp (command, "wallops") == 0)) { split_ok = irc_message_split_string (hashtable, tags, host, command, NULL, ":", (argv_eol[index_args][0] == ':') ? argv_eol[index_args] + 1 : argv_eol[index_args], NULL, ' ', max_length_host); } else if (weechat_strcasecmp (command, "join") == 0) { /* split join (if it's more than 510 bytes) */ if (strlen (message) > 510) { split_ok = irc_message_split_join (hashtable, tags, host, arguments); } } else if ((weechat_strcasecmp (command, "privmsg") == 0) || (weechat_strcasecmp (command, "notice") == 0)) { /* split privmsg/notice */ if (index_args + 1 <= argc - 1) { split_ok = irc_message_split_privmsg_notice (hashtable, tags, host, command, argv[index_args], (argv_eol[index_args + 1][0] == ':') ? argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1], max_length_host); } } else if (weechat_strcasecmp (command, "005") == 0) { /* split 005 (isupport) */ if (index_args + 1 <= argc - 1) { split_ok = irc_message_split_005 (hashtable, tags, host, command, argv[index_args], (argv_eol[index_args + 1][0] == ':') ? argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1]); } } else if (weechat_strcasecmp (command, "353") == 0) { /* * split 353 (list of users on channel): * :server 353 mynick = #channel :mynick nick1 @nick2 +nick3 */ if (index_args + 2 <= argc - 1) { if (irc_channel_is_channel (server, argv[index_args + 1])) { snprintf (target, sizeof (target), "%s %s", argv[index_args], argv[index_args + 1]); split_ok = irc_message_split_string (hashtable, tags, host, command, target, ":", (argv_eol[index_args + 2][0] == ':') ? argv_eol[index_args + 2] + 1 : argv_eol[index_args + 2], NULL, ' ', -1); } else { if (index_args + 3 <= argc - 1) { snprintf (target, sizeof (target), "%s %s %s", argv[index_args], argv[index_args + 1], argv[index_args + 2]); split_ok = irc_message_split_string (hashtable, tags, host, command, target, ":", (argv_eol[index_args + 3][0] == ':') ? argv_eol[index_args + 3] + 1 : argv_eol[index_args + 3], NULL, ' ', -1); } } } } end: if (!split_ok || (weechat_hashtable_get_integer (hashtable, "items_count") == 0)) { irc_message_split_add (hashtable, 1, tags, message, arguments); } if (tags) free (tags); if (argv) weechat_string_free_split (argv); if (argv_eol) weechat_string_free_split (argv_eol); return hashtable; }
int irc_message_split_string (struct t_hashtable *hashtable, const char *tags, const char *host, const char *command, const char *target, const char *prefix, const char *arguments, const char *suffix, const char delimiter, int max_length_host) { const char *pos, *pos_max, *pos_next, *pos_last_delim; char message[1024], *dup_arguments; int max_length, number; max_length = 510; if (max_length_host >= 0) max_length -= max_length_host; else max_length -= (host) ? strlen (host) + 1 : 0; max_length -= strlen (command) + 1; if (target) max_length -= strlen (target); if (prefix) max_length -= strlen (prefix); if (suffix) max_length -= strlen (suffix); if (max_length < 2) return 0; /* debug message */ if (weechat_irc_plugin->debug >= 2) { weechat_printf (NULL, "irc_message_split_string: tags='%s', host='%s', " "command='%s', target='%s', prefix='%s', " "arguments='%s', suffix='%s', max_length=%d", tags, host, command, target, prefix, arguments, suffix, max_length); } number = 1; if (!arguments || !arguments[0]) { snprintf (message, sizeof (message), "%s%s%s %s%s%s%s", (host) ? host : "", (host) ? " " : "", command, (target) ? target : "", (target && target[0]) ? " " : "", (prefix) ? prefix : "", (suffix) ? suffix : ""); irc_message_split_add (hashtable, 1, tags, message, ""); return 1; } while (arguments && arguments[0]) { pos = arguments; pos_max = pos + max_length; pos_last_delim = NULL; while (pos && pos[0]) { if (pos[0] == delimiter) pos_last_delim = pos; pos_next = weechat_utf8_next_char (pos); if (pos_next > pos_max) break; pos = pos_next; } if (pos[0] && pos_last_delim) pos = pos_last_delim; dup_arguments = weechat_strndup (arguments, pos - arguments); if (dup_arguments) { snprintf (message, sizeof (message), "%s%s%s %s%s%s%s%s", (host) ? host : "", (host) ? " " : "", command, (target) ? target : "", (target && target[0]) ? " " : "", (prefix) ? prefix : "", dup_arguments, (suffix) ? suffix : ""); irc_message_split_add (hashtable, number, tags, message, dup_arguments); number++; free (dup_arguments); } arguments = (pos == pos_last_delim) ? pos + 1 : pos; } return 1; }
int irc_message_split_join (struct t_hashtable *hashtable, const char *tags, const char *host, const char *arguments) { int number, channels_count, keys_count, length, length_no_channel; int length_to_add, index_channel; char **channels, **keys, *pos, *str; char msg_to_send[2048], keys_to_add[2048]; number = 1; channels = NULL; channels_count = 0; keys = NULL; keys_count = 0; pos = strchr (arguments, ' '); if (pos) { str = weechat_strndup (arguments, pos - arguments); if (!str) return 0; channels = weechat_string_split (str, ",", 0, 0, &channels_count); free (str); while (pos[0] == ' ') { pos++; } if (pos[0]) keys = weechat_string_split (pos, ",", 0, 0, &keys_count); } else { channels = weechat_string_split (arguments, ",", 0, 0, &channels_count); } snprintf (msg_to_send, sizeof (msg_to_send), "%s%sJOIN", (host) ? host : "", (host) ? " " : ""); length = strlen (msg_to_send); length_no_channel = length; keys_to_add[0] = '\0'; index_channel = 0; while (index_channel < channels_count) { length_to_add = 1 + strlen (channels[index_channel]); if (index_channel < keys_count) length_to_add += 1 + strlen (keys[index_channel]); if ((length + length_to_add < 510) || (length == length_no_channel)) { if (length + length_to_add < (int)sizeof (msg_to_send)) { strcat (msg_to_send, (length == length_no_channel) ? " " : ","); strcat (msg_to_send, channels[index_channel]); } if (index_channel < keys_count) { if (strlen (keys_to_add) + 1 + strlen (keys[index_channel]) < (int)sizeof (keys_to_add)) { strcat (keys_to_add, (keys_to_add[0]) ? "," : " "); strcat (keys_to_add, keys[index_channel]); } } length += length_to_add; index_channel++; } else { strcat (msg_to_send, keys_to_add); irc_message_split_add (hashtable, number, tags, msg_to_send, msg_to_send + length_no_channel + 1); number++; snprintf (msg_to_send, sizeof (msg_to_send), "%s%sJOIN", (host) ? host : "", (host) ? " " : ""); length = strlen (msg_to_send); keys_to_add[0] = '\0'; } } if (length > length_no_channel) { strcat (msg_to_send, keys_to_add); irc_message_split_add (hashtable, number, tags, msg_to_send, msg_to_send + length_no_channel + 1); } if (channels) weechat_string_free_split (channels); if (keys) weechat_string_free_split (keys); return 1; }
struct t_hashtable * irc_message_split (struct t_irc_server *server, const char *message) { struct t_hashtable *hashtable; char **argv, **argv_eol, *tags, *host, *command, *arguments, target[512]; char *pos, monitor_action[3]; int split_ok, argc, index_args, max_length_nick, max_length_host; split_ok = 0; tags = NULL; host = NULL; command = NULL; arguments = NULL; index_args = 0; argv = NULL; argv_eol = NULL; /* debug message */ if (weechat_irc_plugin->debug >= 2) weechat_printf (NULL, "irc_message_split: message='%s'", message); hashtable = weechat_hashtable_new (32, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING, NULL, NULL); if (!hashtable) return NULL; if (!message || !message[0]) goto end; if (message[0] == '@') { pos = strchr (message, ' '); if (pos) { tags = weechat_strndup (message, pos - message + 1); message = pos + 1; } } argv = weechat_string_split (message, " ", 0, 0, &argc); argv_eol = weechat_string_split (message, " ", 2, 0, NULL); if (argc < 2) goto end; if (argv[0][0] == ':') { if (argc < 3) goto end; host = argv[0]; command = argv[1]; arguments = argv_eol[2]; index_args = 2; } else { command = argv[0]; arguments = argv_eol[1]; index_args = 1; } max_length_nick = (server && (server->nick_max_length > 0)) ? server->nick_max_length : 16; max_length_host = 1 + /* ":" */ max_length_nick + /* nick */ 1 + /* "!" */ 63 + /* host */ 1; /* " " */ if ((weechat_strcasecmp (command, "ison") == 0) || (weechat_strcasecmp (command, "wallops") == 0)) { /* * ISON :nick1 nick2 nick3 * WALLOPS :some text here */ split_ok = irc_message_split_string ( hashtable, tags, host, command, NULL, ":", (argv_eol[index_args][0] == ':') ? argv_eol[index_args] + 1 : argv_eol[index_args], NULL, ' ', max_length_host); } else if (weechat_strcasecmp (command, "monitor") == 0) { /* * MONITOR + nick1,nick2,nick3 * MONITOR - nick1,nick2,nick3 */ if (((argv_eol[index_args][0] == '+') || (argv_eol[index_args][0] == '-')) && (argv_eol[index_args][1] == ' ')) { snprintf (monitor_action, sizeof (monitor_action), "%c ", argv_eol[index_args][0]); split_ok = irc_message_split_string ( hashtable, tags, host, command, NULL, monitor_action, argv_eol[index_args] + 2, NULL, ',', max_length_host); } else { split_ok = irc_message_split_string ( hashtable, tags, host, command, NULL, ":", (argv_eol[index_args][0] == ':') ? argv_eol[index_args] + 1 : argv_eol[index_args], NULL, ',', max_length_host); } } else if (weechat_strcasecmp (command, "join") == 0) { /* JOIN #channel1,#channel2,#channel3 key1,key2 */ if (strlen (message) > 510) { /* split join if it's more than 510 bytes */ split_ok = irc_message_split_join (hashtable, tags, host, arguments); } } else if ((weechat_strcasecmp (command, "privmsg") == 0) || (weechat_strcasecmp (command, "notice") == 0)) { /* * PRIVMSG target :some text here * NOTICE target :some text here */ if (index_args + 1 <= argc - 1) { split_ok = irc_message_split_privmsg_notice ( hashtable, tags, host, command, argv[index_args], (argv_eol[index_args + 1][0] == ':') ? argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1], max_length_host); } } else if (weechat_strcasecmp (command, "005") == 0) { /* :server 005 nick MODES=4 CHANLIMIT=#:20 NICKLEN=16 USERLEN=10 ... */ if (index_args + 1 <= argc - 1) { split_ok = irc_message_split_005 ( hashtable, tags, host, command, argv[index_args], (argv_eol[index_args + 1][0] == ':') ? argv_eol[index_args + 1] + 1 : argv_eol[index_args + 1]); } } else if (weechat_strcasecmp (command, "353") == 0) { /* * list of users on channel: * :server 353 mynick = #channel :mynick nick1 @nick2 +nick3 */ if (index_args + 2 <= argc - 1) { if (irc_channel_is_channel (server, argv[index_args + 1])) { snprintf (target, sizeof (target), "%s %s", argv[index_args], argv[index_args + 1]); split_ok = irc_message_split_string ( hashtable, tags, host, command, target, ":", (argv_eol[index_args + 2][0] == ':') ? argv_eol[index_args + 2] + 1 : argv_eol[index_args + 2], NULL, ' ', -1); } else { if (index_args + 3 <= argc - 1) { snprintf (target, sizeof (target), "%s %s %s", argv[index_args], argv[index_args + 1], argv[index_args + 2]); split_ok = irc_message_split_string ( hashtable, tags, host, command, target, ":", (argv_eol[index_args + 3][0] == ':') ? argv_eol[index_args + 3] + 1 : argv_eol[index_args + 3], NULL, ' ', -1); } } } } end: if (!split_ok || (weechat_hashtable_get_integer (hashtable, "items_count") == 0)) { irc_message_split_add (hashtable, 1, tags, message, arguments); } if (tags) free (tags); if (argv) weechat_string_free_split (argv); if (argv_eol) weechat_string_free_split (argv_eol); return hashtable; }