summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Hughart <mekius@mekius.net>2010-10-02 01:50:58 +0000
committerNicholas Hughart <mekius@mekius.net>2010-10-02 01:50:58 +0000
commitfa560f3483338485b66c84a55ac34e0a10b852e8 (patch)
tree2abf27ab7f8204dd12af219a214ac2d6419084cd
parent10f246eca7256d62524bdfae3428dbb7a50bfa0e (diff)
Use eina_strbuf to help with parsing of incoming irc messages and fix a segv.
SVN revision: 52973
-rw-r--r--src/lib/protocols/irc/irc_parse.c351
1 files changed, 185 insertions, 166 deletions
diff --git a/src/lib/protocols/irc/irc_parse.c b/src/lib/protocols/irc/irc_parse.c
index 4bd2056..5ae8604 100644
--- a/src/lib/protocols/irc/irc_parse.c
+++ b/src/lib/protocols/irc/irc_parse.c
@@ -45,183 +45,183 @@ enum _IRC_COMMANDS
45}; 45};
46 46
47/* local function prototypes */ 47/* local function prototypes */
48static Eina_List *_irc_parse_split_input(const char *input);
49static void _irc_cleanup_irc_line(IRC_Line *line); 48static void _irc_cleanup_irc_line(IRC_Line *line);
50static char *_irc_parse_utf8_to_markup(const char *text); 49static char *_irc_parse_utf8_to_markup(const char *text);
51static char *_irc_str_append(char *str, const char *txt, int *len, int *alloc); 50static char *_irc_str_append(char *str, const char *txt, int *len, int *alloc);
52static int _irc_parse_line(const char *line, IRC_Line *out); 51static int _irc_split_line(const char *line, IRC_Line *out);
52static void _irc_parse_line(char *line, const char *server, Emote_Protocol *m);
53static Eina_List *_irc_parse_split_input(Eina_Strbuf **input);
53 54
54void 55void
55irc_parse_input(char *input, const char *server, Emote_Protocol *m) 56irc_parse_input(char *input, const char *server, Emote_Protocol *m)
56{ 57{
57 Emote_Event *event; 58 Eina_List *lines, *l;
58 static char buf[8192]; 59 static Eina_Strbuf *buf = NULL;
59 static int length = 0; 60 char *line;
60 IRC_Line ln;
61 Eina_List *lines, *l, *p;
62 char *line, *param;
63 int size;
64 int ncmd;
65 61
66 if ((length == 1) && (buf[0] == 0)) 62 if (!buf) buf = eina_strbuf_new();
67 length = 0;
68 63
69 strncpy(&(buf[length]), input, sizeof(buf)-length); 64 // Append new data to the buffer
70 length += strlen(input); 65 eina_strbuf_append(buf, input);
66
67 lines = _irc_parse_split_input(&buf);
71 68
72 /* NB: Any parsing of messages after this split will need to append
73 * a new line if printing to the screen as this split strips them out
74 */
75 lines = _irc_parse_split_input(buf);
76 EINA_LIST_FOREACH(lines, l, line) 69 EINA_LIST_FOREACH(lines, l, line)
77 { 70 {
78 printf("Parse Line: %s\n", line); 71 _irc_parse_line(line, server, m);
72 }
79 73
80 size = strlen(line); 74 EINA_LIST_FREE(l, line)
81 length -= size+2; 75 free(line);
82 memmove(buf, &(buf[size+2]), length); 76}
83 buf[length] = 0;
84 77
85 if(!_irc_parse_line(line, &ln)) continue; 78static void
79_irc_parse_line(char *line, const char *server, Emote_Protocol *m)
80{
81 Emote_Event *event;
82 Eina_List *p;
83 char *param;
84 IRC_Line ln;
85 int ncmd;
86 86
87 printf("\tPrefix = %s\n\tSource = %s\n\tUser = %s\n\tHost = %s\n\tCmd: %s\n\tTrailing: %s\n", 87 printf("Parse Line: %s\n", line);
88 ln.prefix, ln.source, ln.user, ln.host, ln.cmd, ln.trailing);
89 EINA_LIST_FOREACH(ln.params, p, param)
90 {
91 printf("\tParam: %s\n", param);
92 }
93 88
94 ncmd = atoi(ln.cmd); 89 if(!_irc_split_line(line, &ln)) return;
95 event = NULL;
96 90
97 if (!strcmp(ln.cmd, "PING")) 91 printf("\tPrefix = %s\n\tSource = %s\n\tUser = %s\n\tHost = %s\n\tCmd: %s\n\tTrailing: %s\n",
98 { 92 ln.prefix, ln.source, ln.user, ln.host, ln.cmd, ln.trailing);
99 protocol_irc_pong(server, eina_list_nth(ln.params,0)); 93 EINA_LIST_FOREACH(ln.params, p, param)
100 } 94 {
101 else if (!strcmp(ln.cmd, "NOTICE")) 95 printf("\tParam: %s\n", param);
102 { 96 }
103 event = emote_event_new(
104 m,
105 EMOTE_EVENT_SERVER_MESSAGE_RECEIVED,
106 server,
107 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
108 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,1))
109 );
110 }
111 else if (!strcmp(ln.cmd, "PRIVMSG"))
112 {
113 event = emote_event_new
114 (
115 m,
116 EMOTE_EVENT_CHAT_MESSAGE_RECEIVED,
117 server,
118 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
119 _irc_parse_utf8_to_markup(ln.source),
120 _irc_parse_utf8_to_markup(ln.trailing)
121 );
122 }
123 else if (!strcmp(ln.cmd, "JOIN"))
124 {
125 event = emote_event_new
126 (
127 m,
128 EMOTE_EVENT_CHAT_JOINED,
129 server,
130 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
131 _irc_parse_utf8_to_markup(ln.source)
132 );
133 }
134 else if (!strcmp(ln.cmd, "PART"))
135 {
136 event = emote_event_new
137 (
138 m,
139 EMOTE_EVENT_CHAT_PARTED,
140 server,
141 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
142 _irc_parse_utf8_to_markup(ln.source)
143 );
144 }
145 else if (!strcmp(ln.cmd, "NICK"))
146 {
147 event = emote_event_new
148 (
149 m,
150 EMOTE_EVENT_SERVER_NICK_CHANGED,
151 server,
152 _irc_parse_utf8_to_markup(ln.source),
153 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0))
154 );
155 }
156 else if (ncmd == RPL_TOPIC)
157 {
158 event = emote_event_new
159 (
160 m,
161 EMOTE_EVENT_CHAT_TOPIC,
162 server,
163 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,1)),
164 NULL,
165 _irc_parse_utf8_to_markup(ln.trailing)
166 );
167 }
168 else if (!strcmp(ln.cmd, "TOPIC"))
169 {
170 event = emote_event_new
171 (
172 m,
173 EMOTE_EVENT_CHAT_TOPIC,
174 server,
175 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
176 _irc_parse_utf8_to_markup(ln.source),
177 _irc_parse_utf8_to_markup(ln.trailing)
178 );
179 }
180 else if (ncmd == RPL_NAMREPLY)
181 {
182 event = emote_event_new
183 (
184 m,
185 EMOTE_EVENT_CHAT_USERS,
186 server,
187 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,2)),
188 NULL,
189 _irc_parse_utf8_to_markup(ln.trailing)
190 );
191 }
192 else if (ncmd == RPL_ENDOFNAMES)
193 {
194 event = emote_event_new
195 (
196 m,
197 EMOTE_EVENT_CHAT_USERS,
198 server,
199 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,1)),
200 NULL,
201 NULL
202 );
203 }
204 else if (ncmd == RPL_TOPICUSER)
205 {
206 // Don't really need to show this.
207 }
208 else if (ncmd != 0)
209 {
210 event = emote_event_new(
211 m,
212 EMOTE_EVENT_SERVER_MESSAGE_RECEIVED,
213 server,
214 NULL,
215 _irc_parse_utf8_to_markup(ln.param_str)
216 );
217 }
218 97
219 if (event) emote_event_send(event); 98 ncmd = atoi(ln.cmd);
220 _irc_cleanup_irc_line(&ln); 99 event = NULL;
100
101 if (!strcmp(ln.cmd, "PING"))
102 {
103 protocol_irc_pong(server, eina_list_nth(ln.params,0));
104 }
105 else if (!strcmp(ln.cmd, "NOTICE"))
106 {
107 event = emote_event_new(
108 m,
109 EMOTE_EVENT_SERVER_MESSAGE_RECEIVED,
110 server,
111 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
112 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,1))
113 );
114 }
115 else if (!strcmp(ln.cmd, "PRIVMSG"))
116 {
117 event = emote_event_new
118 (
119 m,
120 EMOTE_EVENT_CHAT_MESSAGE_RECEIVED,
121 server,
122 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
123 _irc_parse_utf8_to_markup(ln.source),
124 _irc_parse_utf8_to_markup(ln.trailing)
125 );
126 }
127 else if (!strcmp(ln.cmd, "JOIN"))
128 {
129 event = emote_event_new
130 (
131 m,
132 EMOTE_EVENT_CHAT_JOINED,
133 server,
134 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
135 _irc_parse_utf8_to_markup(ln.source)
136 );
137 }
138 else if (!strcmp(ln.cmd, "PART"))
139 {
140 event = emote_event_new
141 (
142 m,
143 EMOTE_EVENT_CHAT_PARTED,
144 server,
145 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
146 _irc_parse_utf8_to_markup(ln.source)
147 );
148 }
149 else if (!strcmp(ln.cmd, "NICK"))
150 {
151 event = emote_event_new
152 (
153 m,
154 EMOTE_EVENT_SERVER_NICK_CHANGED,
155 server,
156 _irc_parse_utf8_to_markup(ln.source),
157 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0))
158 );
159 }
160 else if (ncmd == RPL_TOPIC)
161 {
162 event = emote_event_new
163 (
164 m,
165 EMOTE_EVENT_CHAT_TOPIC,
166 server,
167 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,1)),
168 NULL,
169 _irc_parse_utf8_to_markup(ln.trailing)
170 );
171 }
172 else if (!strcmp(ln.cmd, "TOPIC"))
173 {
174 event = emote_event_new
175 (
176 m,
177 EMOTE_EVENT_CHAT_TOPIC,
178 server,
179 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)),
180 _irc_parse_utf8_to_markup(ln.source),
181 _irc_parse_utf8_to_markup(ln.trailing)
182 );
183 }
184 else if (ncmd == RPL_NAMREPLY)
185 {
186 event = emote_event_new
187 (
188 m,
189 EMOTE_EVENT_CHAT_USERS,
190 server,
191 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,2)),
192 NULL,
193 _irc_parse_utf8_to_markup(ln.trailing)
194 );
195 }
196 else if (ncmd == RPL_ENDOFNAMES)
197 {
198 event = emote_event_new
199 (
200 m,
201 EMOTE_EVENT_CHAT_USERS,
202 server,
203 _irc_parse_utf8_to_markup(eina_list_nth(ln.params,1)),
204 NULL,
205 NULL
206 );
207 }
208 else if (ncmd == RPL_TOPICUSER)
209 {
210 // Don't really need to show this.
211 }
212 else if (ncmd != 0)
213 {
214 event = emote_event_new(
215 m,
216 EMOTE_EVENT_SERVER_MESSAGE_RECEIVED,
217 server,
218 NULL,
219 _irc_parse_utf8_to_markup(ln.param_str)
220 );
221 } 221 }
222 222
223 EINA_LIST_FREE(l, line) 223 if (event) emote_event_send(event);
224 free(line); 224 _irc_cleanup_irc_line(&ln);
225} 225}
226 226
227/* local functions */ 227/* local functions */
@@ -237,19 +237,38 @@ _irc_find_token_pos(const char *buf, int pos, int end, const char token, const c
237} 237}
238 238
239static Eina_List * 239static Eina_List *
240_irc_parse_split_input(const char *input) 240_irc_parse_split_input(Eina_Strbuf **input)
241{ 241{
242 Eina_List *l = NULL; 242 Eina_List *l = NULL;
243 char *tok = NULL, *str, *str2; 243 int i, j, len;
244 char *tok, *str;
245
246 if (!input || !*input) return NULL;
247
248 len = eina_strbuf_length_get(*input);
249 if (len < 2) return NULL;
244 250
245 str2 = str = strdup(input); 251 // Copy strbuf string into a new location that we can modify
246 while ((tok = strsep(&str, "\r\n"))) 252 str = strdup(eina_strbuf_string_get(*input));
253 tok = str;
254 j = 0;
255 for (i = 0; i < (len-1); ++i)
256 {
257 if ((tok[i] == '\r') && (tok[i+1] == '\n'))
247 { 258 {
248 if (!str) break; 259 tok[i++] = 0;
249 if ((*tok == '\0') || (*tok == '\n')) continue; 260
250 l = eina_list_append(l, strdup(tok)); 261 l = eina_list_append(l, strdup(&(tok[j])));
262 j = ++i;
251 } 263 }
252 free(str2); 264 }
265
266 // Update strbuf with remainder
267 eina_strbuf_reset(*input);
268 eina_strbuf_append(*input, &(tok[j]));
269
270 free(str);
271
253 return l; 272 return l;
254} 273}
255 274
@@ -280,7 +299,7 @@ _irc_cleanup_irc_line(IRC_Line *line)
280} 299}
281 300
282static int 301static int
283_irc_parse_line(const char *line, IRC_Line *out) 302_irc_split_line(const char *line, IRC_Line *out)
284{ 303{
285 char buf[8192]; 304 char buf[8192];
286 PARSE_STATE state; 305 PARSE_STATE state;