Mercurial > pidgin.yaz
annotate src/protocols/icq/icqevent.c @ 5191:092b418b5012
[gaim-migrate @ 5556]
truncate non-utf8 friendly names, rather than crashing.
committer: Tailor Script <tailor@pidgin.im>
author | Nathan Walp <nwalp@pidgin.im> |
---|---|
date | Tue, 22 Apr 2003 05:39:03 +0000 |
parents | f0a2a9afdb77 |
children |
rev | line source |
---|---|
2086 | 1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | |
3 /* | |
2496
f0a2a9afdb77
[gaim-migrate @ 2509]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
4 * $Id: icqevent.c 2509 2001-10-13 00:06:18Z warmenhoven $ |
2086 | 5 * |
6 * Copyright (C) 1998-2001, Denis V. Dmitrienko <denis@null.net> and | |
7 * Bill Soudan <soudan@kde.org> | |
8 * | |
9 * This program is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU General Public License as published by | |
11 * the Free Software Foundation; either version 2 of the License, or | |
12 * (at your option) any later version. | |
13 * | |
14 * This program is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 * GNU General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU General Public License | |
20 * along with this program; if not, write to the Free Software | |
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 * | |
23 */ | |
24 | |
25 #include <stdlib.h> | |
26 | |
27 #include "icqlib.h" /* for icqbyteorder.h ?! */ | |
28 #include "icqbyteorder.h" | |
29 #include "icqevent.h" | |
30 | |
31 #ifdef EVENT_DEBUG | |
32 #include <string.h> | |
33 #include <stdio.h> | |
34 #endif | |
35 | |
36 #define new_event(x, y) y * x = ( y * )malloc(sizeof(y)) | |
37 | |
38 /* generic Event - 'header' for each tcp packet */ | |
39 | |
40 void icq_EventInit(icq_Event *p, int type, int subtype, unsigned long uin, | |
41 int version) | |
42 { | |
43 if (!p) | |
44 return; | |
45 | |
46 p->uin=uin; | |
47 p->version=version; | |
48 p->type=type; | |
49 p->subtype=subtype; | |
50 p->direction=ICQ_EVENT_OUTGOING; | |
51 } | |
52 | |
53 icq_Packet *icq_EventCreatePacket(icq_Event *pbase) | |
54 { | |
55 icq_Packet *p=icq_PacketNew(); | |
56 | |
57 /* create header for tcp packet */ | |
58 icq_PacketAppend32(p, pbase->uin); | |
59 icq_PacketAppend16(p, pbase->version); | |
60 icq_PacketAppend16(p, pbase->subtype); | |
61 icq_PacketAppend16(p, 0x0000); | |
62 icq_PacketAppend32(p, pbase->uin); | |
63 icq_PacketAppend32(p, pbase->type); | |
64 | |
65 return p; | |
66 } | |
67 | |
68 void icq_EventParsePacket(icq_Event *pevent, icq_Packet *p) | |
69 { | |
70 /* parse header of tcp packet */ | |
71 icq_PacketBegin(p); | |
72 (void)icq_PacketRead32(p); /* uin */ | |
73 pevent->version=icq_PacketRead16(p); /* max supported tcp version */ | |
74 pevent->subtype=icq_PacketRead16(p); /* event subtype */ | |
75 (void)icq_PacketRead16(p); /* 0x0000 */ | |
76 pevent->uin=icq_PacketRead32(p); /* uin */ | |
77 pevent->type=icq_PacketRead16(p); /* event type */ | |
78 } | |
79 | |
80 /* Message Event - extends generic Event */ | |
81 | |
82 icq_MessageEvent *icq_CreateMessageEvent(int subtype, unsigned long uin, | |
83 const char *message) | |
84 { | |
85 new_event(p, icq_MessageEvent); | |
86 icq_Event *pbase=(icq_Event *)p; | |
87 icq_MessageEventInit(p, ICQ_TCP_MSG_MSG, subtype, uin, | |
88 ICQ_TCP_MSG_REAL, message); | |
89 | |
90 pbase->createPacket=icq_MessageCreatePacket; | |
91 | |
92 #ifdef EVENT_DEBUG | |
93 pbase->eventName=icq_MessageEventName; | |
94 pbase->eventDump=icq_MessageEventDump; | |
95 #endif | |
96 | |
97 return p; | |
98 } | |
99 | |
100 void icq_MessageEventInit(icq_MessageEvent *p, int type, int subtype, | |
101 unsigned long uin, int msgtype, const char *message) | |
102 { | |
103 icq_EventInit((icq_Event *)p, type, subtype, uin, ICQ_TCP_VER); | |
104 p->type=msgtype; | |
105 p->message=(char *)message; | |
106 p->status=0; /* FIXME */ | |
107 } | |
108 | |
109 icq_Packet *icq_MessageCreatePacket(icq_Event *pbase, icq_TCPLink *plink) | |
110 { | |
111 icq_MessageEvent *pevent=(icq_MessageEvent *)pbase; | |
112 | |
113 /* create header */ | |
114 icq_Packet *p=icq_EventCreatePacket(pbase); | |
115 | |
116 /* append data specific to message event */ | |
117 icq_PacketAppendString(p, (char*)pevent->message); | |
118 icq_PacketAppend32(p, plink->socket_address.sin_addr.s_addr); | |
119 /* FIXME: should be RealIp */ | |
120 icq_PacketAppend32(p, htonl(plink->icqlink->icq_OurIP)); | |
121 icq_PacketAppend32(p, plink->socket_address.sin_port); | |
122 icq_PacketAppend8(p, 0x04); | |
123 icq_PacketAppend16(p, pevent->status); | |
124 icq_PacketAppend16(p, pevent->type); | |
125 | |
126 return p; | |
127 } | |
128 | |
129 void icq_MessageParsePacket(icq_Event *pbase, icq_Packet *p) | |
130 { | |
131 icq_MessageEvent *pevent=(icq_MessageEvent *)pbase; | |
132 | |
133 /* parse message event data from packet */ | |
134 pevent->message=(char *)icq_PacketReadString(p); /* message text */ | |
135 (void)icq_PacketRead32(p); /* remote ip */ | |
136 (void)icq_PacketRead32(p); /* remote real ip */ | |
137 (void)icq_PacketRead32(p); /* remote message port */ | |
138 (void)icq_PacketRead8(p); /* tcp flag */ | |
139 pevent->status=icq_PacketRead16(p); /* remote user status */ | |
140 pevent->type=icq_PacketRead16(p); /* message type */ | |
141 } | |
142 | |
143 #ifdef EVENT_DEBUG | |
144 const char *icq_MessageEventName(icq_Event *p) | |
145 { | |
146 if (p->type==ICQ_EVENT_MESSAGE) | |
147 return "message"; | |
148 else if (p->type==ICQ_EVENT_ACK) | |
149 return "message ack"; | |
150 | |
151 return "message cancel"; | |
152 } | |
153 | |
154 const char *icq_MessageEventDump(icq_Event *p) | |
155 { | |
156 static char buf[255]; | |
157 icq_MessageEvent *pevent=(icq_MessageEvent *)p; | |
158 | |
159 sprintf(buf, ", type=%x, message=\"%10s...\", status=%x", | |
160 pevent->type, pevent->message, pevent->status); | |
161 | |
162 return buf; | |
163 } | |
164 #endif | |
165 | |
166 /* URL Event - extends message Event */ | |
167 | |
168 icq_URLEvent *icq_CreateURLEvent(int subtype, unsigned long uin, | |
169 const char *message, const char *url) | |
170 { | |
171 char *str=(char *)malloc(strlen(message)+strlen(url)+2); | |
172 icq_Event *pbase; | |
173 icq_URLEvent *p; | |
174 | |
175 strcpy((char*)str, message); | |
176 *(str+strlen(message))=0xFE; | |
177 strcpy((char*)(str+strlen(message)+1), url); | |
178 | |
179 /* TODO: make sure create message event copies message */ | |
180 pbase=(icq_Event *)icq_CreateMessageEvent(subtype, uin, str); | |
181 p=(icq_URLEvent *)pbase; | |
182 | |
183 free(str); | |
184 | |
185 *(p->message+strlen(message))=0x00; | |
186 p->url=p->message+strlen(message)+1; | |
187 | |
188 pbase->createPacket=icq_URLCreatePacket; | |
189 | |
190 #ifdef EVENT_DEBUG | |
191 pbase->eventName=icq_URLEventName; | |
192 pbase->eventDump=icq_URLEventDump; | |
193 #endif | |
194 | |
195 return p; | |
196 | |
197 } | |
198 | |
199 icq_Packet *icq_URLCreatePacket(icq_Event *pbase, icq_TCPLink *plink) | |
200 { | |
201 icq_URLEvent *pevent=(icq_URLEvent *)pbase; | |
202 icq_Packet *p; | |
203 | |
204 /* hack message string to include url */ | |
205 *(pevent->message+strlen(pevent->message))=0xFE; | |
206 | |
207 /* create packet */ | |
208 p=icq_MessageCreatePacket(pbase, plink); | |
209 | |
210 /* hack message string to seperate url */ | |
211 *(pevent->message+strlen(pevent->message))=0x00; | |
212 | |
213 return p; | |
214 } | |
215 | |
216 void icq_URLParsePacket(icq_Event *pbase, icq_Packet *p) | |
217 { | |
218 char *pfe; | |
219 icq_URLEvent *pevent=(icq_URLEvent *)pbase; | |
220 | |
221 /* TODO: make sure messageparsepacket allocates message string | |
222 * and add a delete event function */ | |
223 icq_MessageParsePacket(pbase, p); | |
224 | |
225 /* hack message string to seperate url */ | |
226 pfe=strchr(pevent->message, '\xFE'); | |
227 *pfe=0; | |
228 | |
229 /* set url */ | |
230 pevent->url=pfe+1; | |
231 | |
232 } | |
233 | |
234 #ifdef EVENT_DEBUG | |
235 const char *icq_URLEventName(icq_Event *p) | |
236 { | |
237 if (p->type==ICQ_EVENT_MESSAGE) | |
238 return "url"; | |
239 else if (p->type==ICQ_EVENT_ACK) | |
240 return "url ack"; | |
241 | |
242 return "url cancel"; | |
243 } | |
244 | |
245 const char *icq_URLEventDump(icq_Event *p) | |
246 { | |
247 static char buf[255]; | |
248 icq_MessageEvent *pevent=(icq_MessageEvent *)p; | |
249 | |
250 sprintf(buf, ", type=%x, message=\"%10s...\", url=\"%10s...\" status=%x", | |
251 pevent->type, pevent->message, pevent->url, pevent->status); | |
252 | |
253 return buf; | |
254 } | |
255 #endif | |
256 | |
257 | |
258 /* Chat Request Event - extends Message Event */ | |
259 | |
260 icq_ChatRequestEvent *icq_ChatRequestEventNew(int subtype, | |
261 unsigned long uin, const char *message, int port) | |
262 { | |
263 new_event(p, icq_ChatRequestEvent); | |
264 icq_Event *pbase=(icq_Event *)p; | |
265 icq_MessageEventInit((icq_MessageEvent *)p, ICQ_TCP_MSG_CHAT, subtype, | |
266 uin, ICQ_TCP_MSG_REAL, message); | |
267 p->port=port; | |
268 | |
269 pbase->createPacket=icq_ChatRequestCreatePacket; | |
270 | |
271 #ifdef EVENT_DEBUG | |
272 pbase->eventName=icq_ChatRequestEventName; | |
273 pbase->eventDump=icq_ChatRequestEventDump; | |
274 #endif | |
275 | |
276 return p; | |
277 } | |
278 | |
279 icq_Packet *icq_ChatRequestCreatePacket(icq_Event *pbase, | |
280 icq_TCPLink *plink) | |
281 { | |
282 icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase; | |
283 | |
284 /* create header and message data */ | |
285 icq_Packet *p=icq_MessageCreatePacket(pbase, plink); | |
286 | |
287 /* append data specific to chat event */ | |
288 icq_PacketAppendString(p, 0); | |
289 icq_PacketAppend32(p, htonl(pevent->port)); | |
290 icq_PacketAppend32(p, htoicql(pevent->port)); | |
291 | |
292 return p; | |
293 } | |
294 | |
295 void icq_ChatParsePacket(icq_Event *pbase, icq_Packet *p) | |
296 { | |
297 icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase; | |
298 int port; | |
299 | |
300 /* parse header and message event data */ | |
301 icq_MessageParsePacket(pbase, p); | |
302 | |
303 /* parse chat event data */ | |
304 (void)icq_PacketReadString(p); /* null string */ | |
305 port=icq_PacketRead32(p); /* chat listen port, network order */ | |
306 (void)icq_PacketRead32(p); /* chat listen port, intel order */ | |
307 | |
308 pevent->port=ntohl(port); | |
309 } | |
310 | |
311 #ifdef EVENT_DEBUG | |
312 const char *icq_ChatRequestEventName(icq_Event *p) | |
313 { | |
314 if (p->type==ICQ_EVENT_MESSAGE) | |
315 return "chat request"; | |
316 else if (p->type==ICQ_EVENT_ACK) { | |
317 icq_MessageEvent *pevent=(icq_MessageEvent *)p; | |
318 if (pevent->status==ICQ_TCP_STATUS_REFUSE) | |
319 return "chat request refuse"; | |
320 else | |
321 return "chat request ack"; | |
322 } else if (p->type==ICQ_EVENT_CANCEL) | |
323 return "chat request cancel"; | |
324 | |
325 return "unknown chat request"; | |
326 } | |
327 | |
328 const char *icq_ChatRequestEventDump(icq_Event *p) | |
329 { | |
330 static char buf[255]; | |
331 static char buf2[255]; | |
332 icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)p; | |
333 | |
334 strcpy(buf, icq_MessageEventDump(p)); | |
335 sprintf(buf2, ", port=%d", pevent->port); | |
336 strcat(buf, buf2); | |
337 | |
338 return buf; | |
339 } | |
340 #endif | |
341 | |
342 /* File Request Event - builds on Message Event */ | |
343 | |
344 icq_FileRequestEvent *icq_FileRequestEventNew(int subtype, | |
345 unsigned long uin, const char *message, const char *filename, | |
346 unsigned long filesize) | |
347 { | |
348 new_event(p, icq_FileRequestEvent); | |
349 icq_Event *pbase=(icq_Event *)p; | |
350 icq_MessageEventInit((icq_MessageEvent *)p, ICQ_TCP_MSG_FILE, subtype, | |
351 uin, ICQ_TCP_MSG_REAL, message); | |
352 p->filename=filename; | |
353 p->filesize=filesize; | |
354 | |
355 pbase->createPacket=icq_FileRequestCreatePacket; | |
356 | |
357 #ifdef EVENT_DEBUG | |
358 pbase->eventName=icq_FileRequestEventName; | |
359 pbase->eventDump=icq_FileRequestEventDump; | |
360 #endif | |
361 | |
362 return p; | |
363 } | |
364 | |
365 icq_Packet *icq_FileRequestCreatePacket(icq_Event *pbase, | |
366 icq_TCPLink *plink) | |
367 { | |
368 icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase; | |
369 | |
370 /* create header and message data */ | |
371 icq_Packet *p=icq_MessageCreatePacket(pbase, plink); | |
372 | |
373 /* append file event data */ | |
374 icq_PacketAppend32(p, htonl(pevent->port)); | |
375 icq_PacketAppendString(p, pevent->filename); | |
376 icq_PacketAppend32(p, pevent->filesize); | |
377 icq_PacketAppend32(p, htoicql(pevent->port)); | |
378 | |
379 return p; | |
380 } | |
381 | |
382 void icq_FileParsePacket(icq_Event *pbase, icq_Packet *p) | |
383 { | |
384 icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase; | |
385 | |
386 /* parse header and message data */ | |
387 icq_MessageParsePacket(pbase, p); | |
388 | |
389 /* parse file event data */ | |
390 pevent->port=ntohl(icq_PacketRead32(p)); /* file listen port, network */ | |
391 pevent->filename=icq_PacketReadString(p); /* filename text */ | |
392 pevent->filesize=icq_PacketRead32(p); /* total size */ | |
393 (void)icq_PacketRead32(p); /* file listen port, intel */ | |
394 } | |
395 | |
396 #ifdef EVENT_DEBUG | |
397 const char *icq_FileRequestEventName(icq_Event *p) | |
398 { | |
399 if (p->type==ICQ_EVENT_MESSAGE) | |
400 return "file request"; | |
401 else if (p->type==ICQ_EVENT_ACK) { | |
402 icq_MessageEvent *pevent=(icq_MessageEvent *)p; | |
403 if (pevent->status==ICQ_TCP_STATUS_REFUSE) | |
404 return "file request refuse"; | |
405 else | |
406 return "file request ack"; | |
407 } else if (p->type==ICQ_EVENT_CANCEL) | |
408 return "file request cancel"; | |
409 | |
410 return "unknown file request"; | |
411 } | |
412 | |
413 const char *icq_FileRequestEventDump(icq_Event *p) | |
414 { | |
415 static char buf[255]; | |
416 static char buf2[255]; | |
417 icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)p; | |
418 | |
419 strcpy(buf, icq_MessageEventDump(p)); | |
420 sprintf(buf2, ", port=%d, filename=\"%s\", filesize=%ld", pevent->port, | |
421 pevent->filename, pevent->filesize); | |
422 strcat(buf, buf2); | |
423 | |
424 return buf; | |
425 } | |
426 #endif | |
427 | |
428 /* main packet parser */ | |
429 | |
430 icq_Event *icq_ParsePacket(icq_Packet *p) | |
431 { | |
432 /* FIXME */ | |
433 icq_Event *pevent=(icq_Event *)malloc(sizeof(icq_FileRequestEvent)); | |
434 pevent->direction=ICQ_EVENT_INCOMING; | |
435 pevent->time=time(0); | |
436 | |
437 icq_EventParsePacket(pevent, p); | |
438 | |
439 switch(pevent->type) { | |
440 | |
441 case ICQ_TCP_MSG_MSG: | |
442 icq_MessageParsePacket(pevent, p); | |
443 break; | |
444 case ICQ_TCP_MSG_URL: | |
445 icq_URLParsePacket(pevent, p); | |
446 break; | |
447 case ICQ_TCP_MSG_CHAT: | |
448 icq_ChatParsePacket(pevent, p); | |
449 break; | |
450 case ICQ_TCP_MSG_FILE: | |
451 icq_FileParsePacket(pevent, p); | |
452 break; | |
453 default: | |
454 /* FIXME: log */ | |
455 free(pevent); | |
456 pevent=0; | |
457 break; | |
458 } | |
459 | |
460 /* FIXME: ensure no bytes are remaining */ | |
461 | |
462 return pevent; | |
463 } | |
464 | |
465 #ifdef EVENT_DEBUG | |
466 const char *icq_EventDump(icq_Event *pevent) | |
467 { | |
468 static char buf[255]; | |
469 | |
470 sprintf("%s event sent to uin %ld { %s }", (pevent->eventName)(pevent), | |
471 pevent->uin, (pevent->eventDump)(pevent) ); | |
472 | |
473 return buf; | |
474 } | |
475 #endif |