libpurple/protocols/irc/parse.c

branch
release-2.x.y
changeset 35245
a167504359e5
parent 33809
d5e9c888ccd7
child 35248
9f132a6855cd
equal deleted inserted replaced
35244:2bb66ef1475e 35245:a167504359e5
48 48
49 /*typedef void (*IRCMsgCallback)(struct irc_conn *irc, char *from, char *name, char **args);*/ 49 /*typedef void (*IRCMsgCallback)(struct irc_conn *irc, char *from, char *name, char **args);*/
50 static struct _irc_msg { 50 static struct _irc_msg {
51 char *name; 51 char *name;
52 char *format; 52 char *format;
53 int req_cnt;
53 void (*cb)(struct irc_conn *irc, const char *name, const char *from, char **args); 54 void (*cb)(struct irc_conn *irc, const char *name, const char *from, char **args);
54 } _irc_msgs[] = { 55 } _irc_msgs[] = {
55 { "005", "n*", irc_msg_features }, /* Feature list */ 56 { "005", "n*", -1, irc_msg_features }, /* Feature list */
56 { "251", "n:", irc_msg_luser }, /* Client & Server count */ 57 { "251", "n:", -1, irc_msg_luser }, /* Client & Server count */
57 { "255", "n:", irc_msg_luser }, /* Client & Server count Mk. II */ 58 { "255", "n:", -1, irc_msg_luser }, /* Client & Server count Mk. II */
58 { "301", "nn:", irc_msg_away }, /* User is away */ 59 { "301", "nn:", -1, irc_msg_away }, /* User is away */
59 { "303", "n:", irc_msg_ison }, /* ISON reply */ 60 { "303", "n:", -1, irc_msg_ison }, /* ISON reply */
60 { "311", "nnvvv:", irc_msg_whois }, /* Whois user */ 61 { "311", "nnvvv:", -1, irc_msg_whois }, /* Whois user */
61 { "312", "nnv:", irc_msg_whois }, /* Whois server */ 62 { "312", "nnv:", -1, irc_msg_whois }, /* Whois server */
62 { "313", "nn:", irc_msg_whois }, /* Whois ircop */ 63 { "313", "nn:", -1, irc_msg_whois }, /* Whois ircop */
63 { "317", "nnvv", irc_msg_whois }, /* Whois idle */ 64 { "317", "nnvv", -1, irc_msg_whois }, /* Whois idle */
64 { "318", "nt:", irc_msg_endwhois }, /* End of WHOIS */ 65 { "318", "nt:", -1, irc_msg_endwhois }, /* End of WHOIS */
65 { "319", "nn:", irc_msg_whois }, /* Whois channels */ 66 { "319", "nn:", -1, irc_msg_whois }, /* Whois channels */
66 { "320", "nn:", irc_msg_whois }, /* Whois (fn ident) */ 67 { "320", "nn:", -1, irc_msg_whois }, /* Whois (fn ident) */
67 { "314", "nnnvv:", irc_msg_whois }, /* Whowas user */ 68 { "314", "nnnvv:", -1, irc_msg_whois }, /* Whowas user */
68 { "315", "nt:", irc_msg_who }, /* end of WHO channel */ 69 { "315", "nt:", -1, irc_msg_who }, /* end of WHO channel */
69 { "369", "nt:", irc_msg_endwhois }, /* End of WHOWAS */ 70 { "369", "nt:", -1, irc_msg_endwhois }, /* End of WHOWAS */
70 { "321", "*", irc_msg_list }, /* Start of list */ 71 { "321", "*", -1, irc_msg_list }, /* Start of list */
71 { "322", "ncv:", irc_msg_list }, /* List. */ 72 { "322", "ncv:", -1, irc_msg_list }, /* List. */
72 { "323", ":", irc_msg_list }, /* End of list. */ 73 { "323", ":", -1, irc_msg_list }, /* End of list. */
73 { "324", "ncv:", irc_msg_chanmode }, /* Channel modes */ 74 { "324", "ncv:", -1, irc_msg_chanmode }, /* Channel modes */
74 { "331", "nc:", irc_msg_topic }, /* No channel topic */ 75 { "331", "nc:", -1, irc_msg_topic }, /* No channel topic */
75 { "332", "nc:", irc_msg_topic }, /* Channel topic */ 76 { "332", "nc:", -1, irc_msg_topic }, /* Channel topic */
76 { "333", "ncvv", irc_msg_topicinfo }, /* Topic setter stuff */ 77 { "333", "ncvv", -1, irc_msg_topicinfo }, /* Topic setter stuff */
77 { "352", "ncvvvnv:", irc_msg_who }, /* Channel WHO */ 78 { "352", "ncvvvnv:", -1, irc_msg_who }, /* Channel WHO */
78 { "353", "nvc:", irc_msg_names }, /* Names list */ 79 { "353", "nvc:", -1, irc_msg_names }, /* Names list */
79 { "366", "nc:", irc_msg_names }, /* End of names */ 80 { "366", "nc:", -1, irc_msg_names }, /* End of names */
80 { "367", "ncnnv", irc_msg_ban }, /* Ban list */ 81 { "367", "ncnnv", -1, irc_msg_ban }, /* Ban list */
81 { "368", "nc:", irc_msg_ban }, /* End of ban list */ 82 { "368", "nc:", -1, irc_msg_ban }, /* End of ban list */
82 { "372", "n:", irc_msg_motd }, /* MOTD */ 83 { "372", "n:", -1, irc_msg_motd }, /* MOTD */
83 { "375", "n:", irc_msg_motd }, /* Start MOTD */ 84 { "375", "n:", -1, irc_msg_motd }, /* Start MOTD */
84 { "376", "n:", irc_msg_motd }, /* End of MOTD */ 85 { "376", "n:", -1, irc_msg_motd }, /* End of MOTD */
85 { "391", "nv:", irc_msg_time }, /* Time reply */ 86 { "391", "nv:", -1, irc_msg_time }, /* Time reply */
86 { "401", "nt:", irc_msg_nonick }, /* No such nick/chan */ 87 { "401", "nt:", -1, irc_msg_nonick }, /* No such nick/chan */
87 { "406", "nt:", irc_msg_nonick }, /* No such nick for WHOWAS */ 88 { "406", "nt:", -1, irc_msg_nonick }, /* No such nick for WHOWAS */
88 { "403", "nc:", irc_msg_nochan }, /* No such channel */ 89 { "403", "nc:", -1, irc_msg_nochan }, /* No such channel */
89 { "404", "nt:", irc_msg_nosend }, /* Cannot send to chan */ 90 { "404", "nt:", -1, irc_msg_nosend }, /* Cannot send to chan */
90 { "421", "nv:", irc_msg_unknown }, /* Unknown command */ 91 { "421", "nv:", -1, irc_msg_unknown }, /* Unknown command */
91 { "422", "n:", irc_msg_motd }, /* MOTD file missing */ 92 { "422", "n:", -1, irc_msg_motd }, /* MOTD file missing */
92 { "432", "vn:", irc_msg_badnick }, /* Erroneous nickname */ 93 { "432", "vn:", -1, irc_msg_badnick }, /* Erroneous nickname */
93 { "433", "vn:", irc_msg_nickused }, /* Nickname already in use */ 94 { "433", "vn:", -1, irc_msg_nickused }, /* Nickname already in use */
94 { "437", "nc:", irc_msg_unavailable }, /* Nick/channel is unavailable */ 95 { "437", "nc:", -1, irc_msg_unavailable }, /* Nick/channel is unavailable */
95 { "438", "nn:", irc_msg_nochangenick }, /* Nick may not change */ 96 { "438", "nn:", -1, irc_msg_nochangenick }, /* Nick may not change */
96 { "442", "nc:", irc_msg_notinchan }, /* Not in channel */ 97 { "442", "nc:", -1, irc_msg_notinchan }, /* Not in channel */
97 { "473", "nc:", irc_msg_inviteonly }, /* Tried to join invite-only */ 98 { "473", "nc:", -1, irc_msg_inviteonly }, /* Tried to join invite-only */
98 { "474", "nc:", irc_msg_banned }, /* Banned from channel */ 99 { "474", "nc:", -1, irc_msg_banned }, /* Banned from channel */
99 { "477", "nc:", irc_msg_regonly }, /* Registration Required */ 100 { "477", "nc:", -1, irc_msg_regonly }, /* Registration Required */
100 { "478", "nct:", irc_msg_banfull }, /* Banlist is full */ 101 { "478", "nct:", -1, irc_msg_banfull }, /* Banlist is full */
101 { "482", "nc:", irc_msg_notop }, /* Need to be op to do that */ 102 { "482", "nc:", -1, irc_msg_notop }, /* Need to be op to do that */
102 { "501", "n:", irc_msg_badmode }, /* Unknown mode flag */ 103 { "501", "n:", -1, irc_msg_badmode }, /* Unknown mode flag */
103 { "506", "nc:", irc_msg_nosend }, /* Must identify to send */ 104 { "506", "nc:", -1, irc_msg_nosend }, /* Must identify to send */
104 { "515", "nc:", irc_msg_regonly }, /* Registration required */ 105 { "515", "nc:", -1, irc_msg_regonly }, /* Registration required */
105 #ifdef HAVE_CYRUS_SASL 106 #ifdef HAVE_CYRUS_SASL
106 { "903", "*", irc_msg_authok}, /* SASL auth successful */ 107 { "903", "*", -1, irc_msg_authok}, /* SASL auth successful */
107 { "904", "*", irc_msg_authtryagain }, /* SASL auth failed, can recover */ 108 { "904", "*", -1, irc_msg_authtryagain }, /* SASL auth failed, can recover*/
108 { "905", "*", irc_msg_authfail }, /* SASL auth failed */ 109 { "905", "*", -1, irc_msg_authfail }, /* SASL auth failed */
109 { "906", "*", irc_msg_authfail }, /* SASL auth failed */ 110 { "906", "*", -1, irc_msg_authfail }, /* SASL auth failed */
110 { "907", "*", irc_msg_authfail }, /* SASL auth failed */ 111 { "907", "*", -1, irc_msg_authfail }, /* SASL auth failed */
111 { "cap", "vv:", irc_msg_cap }, /* SASL capable */ 112 { "cap", "vv:", -1, irc_msg_cap }, /* SASL capable */
112 #endif 113 #endif
113 { "invite", "n:", irc_msg_invite }, /* Invited */ 114 { "invite", "n:", -1, irc_msg_invite }, /* Invited */
114 { "join", ":", irc_msg_join }, /* Joined a channel */ 115 { "join", ":", -1, irc_msg_join }, /* Joined a channel */
115 { "kick", "cn:", irc_msg_kick }, /* KICK */ 116 { "kick", "cn:", -1, irc_msg_kick }, /* KICK */
116 { "mode", "tv:", irc_msg_mode }, /* MODE for channel */ 117 { "mode", "tv:", -1, irc_msg_mode }, /* MODE for channel */
117 { "nick", ":", irc_msg_nick }, /* Nick change */ 118 { "nick", ":", -1, irc_msg_nick }, /* Nick change */
118 { "notice", "t:", irc_msg_notice }, /* NOTICE recv */ 119 { "notice", "t:", -1, irc_msg_notice }, /* NOTICE recv */
119 { "part", "c:", irc_msg_part }, /* Parted a channel */ 120 { "part", "c:", -1, irc_msg_part }, /* Parted a channel */
120 { "ping", ":", irc_msg_ping }, /* Received PING from server */ 121 { "ping", ":", -1, irc_msg_ping }, /* Received PING from server */
121 { "pong", "v:", irc_msg_pong }, /* Received PONG from server */ 122 { "pong", "v:", -1, irc_msg_pong }, /* Received PONG from server */
122 { "privmsg", "t:", irc_msg_privmsg }, /* Received private message */ 123 { "privmsg", "t:", -1, irc_msg_privmsg }, /* Received private message */
123 { "topic", "c:", irc_msg_topic }, /* TOPIC command */ 124 { "topic", "c:", -1, irc_msg_topic }, /* TOPIC command */
124 { "quit", ":", irc_msg_quit }, /* QUIT notice */ 125 { "quit", ":", -1, irc_msg_quit }, /* QUIT notice */
125 { "wallops", ":", irc_msg_wallops }, /* WALLOPS command */ 126 { "wallops", ":", -1, irc_msg_wallops }, /* WALLOPS command */
126 { NULL, NULL, NULL } 127 { NULL, NULL, 0, NULL }
127 }; 128 };
128 129
129 static struct _irc_user_cmd { 130 static struct _irc_user_cmd {
130 char *name; 131 char *name;
131 char *format; 132 char *format;
660 { 661 {
661 struct _irc_msg *msgent; 662 struct _irc_msg *msgent;
662 char *cur, *end, *tmp, *from, *msgname, *fmt, **args, *msg; 663 char *cur, *end, *tmp, *from, *msgname, *fmt, **args, *msg;
663 guint i; 664 guint i;
664 PurpleConnection *gc = purple_account_get_connection(irc->account); 665 PurpleConnection *gc = purple_account_get_connection(irc->account);
666 gboolean fmt_valid;
667 int args_cnt;
665 668
666 irc->recv_time = time(NULL); 669 irc->recv_time = time(NULL);
667 670
668 /* 671 /*
669 * The data passed to irc-receiving-text is the raw protocol data. 672 * The data passed to irc-receiving-text is the raw protocol data.
716 g_free(from); 719 g_free(from);
717 return; 720 return;
718 } 721 }
719 g_free(msgname); 722 g_free(msgname);
720 723
724 fmt_valid = TRUE;
721 args = g_new0(char *, strlen(msgent->format)); 725 args = g_new0(char *, strlen(msgent->format));
726 args_cnt = 0;
722 for (cur = end, fmt = msgent->format, i = 0; fmt[i] && *cur++; i++) { 727 for (cur = end, fmt = msgent->format, i = 0; fmt[i] && *cur++; i++) {
723 switch (fmt[i]) { 728 switch (fmt[i]) {
724 case 'v': 729 case 'v':
725 if (!(end = strchr(cur, ' '))) end = cur + strlen(cur); 730 if (!(end = strchr(cur, ' '))) end = cur + strlen(cur);
726 /* This is a string of unknown encoding which we do not 731 /* This is a string of unknown encoding which we do not
753 args[i] = purple_utf8_salvage(cur); 758 args[i] = purple_utf8_salvage(cur);
754 cur = cur + strlen(cur); 759 cur = cur + strlen(cur);
755 break; 760 break;
756 default: 761 default:
757 purple_debug(PURPLE_DEBUG_ERROR, "irc", "invalid message format character '%c'\n", fmt[i]); 762 purple_debug(PURPLE_DEBUG_ERROR, "irc", "invalid message format character '%c'\n", fmt[i]);
758 break; 763 fmt_valid = FALSE;
759 } 764 break;
760 } 765 }
761 tmp = irc_recv_convert(irc, from); 766 if (fmt_valid)
762 (msgent->cb)(irc, msgent->name, tmp, args); 767 args_cnt = i + 1;
763 g_free(tmp); 768 }
769 if (G_UNLIKELY(!fmt_valid)) {
770 purple_debug_error("irc", "message format was invalid");
771 } else if (G_LIKELY(args_cnt >= msgent->req_cnt)) {
772 tmp = irc_recv_convert(irc, from);
773 (msgent->cb)(irc, msgent->name, tmp, args);
774 g_free(tmp);
775 } else {
776 purple_debug_error("irc", "args count (%d) doesn't reach "
777 "expected value of %d for the '%s' command",
778 args_cnt, msgent->req_cnt, msgent->name);
779 }
764 for (i = 0; i < strlen(msgent->format); i++) { 780 for (i = 0; i < strlen(msgent->format); i++) {
765 g_free(args[i]); 781 g_free(args[i]);
766 } 782 }
767 g_free(args); 783 g_free(args);
768 g_free(from); 784 g_free(from);

mercurial