1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
4 * $Id: icqevent.c 2509 2001-10-13 00:06:18Z warmenhoven $
6 * Copyright (C) 1998-2001, Denis V. Dmitrienko <denis@null.net> and
7 * Bill Soudan <soudan@kde.org>
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.
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.
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.
27 #include "icqlib.h" /* for icqbyteorder.h ?! */
28 #include "icqbyteorder.h"
36 #define new_event(x, y) y * x = ( y * )malloc(sizeof(y))
38 /* generic Event - 'header' for each tcp packet */
40 void icq_EventInit(icq_Event
*p
, int type
, int subtype
, unsigned long uin
,
50 p
->direction
=ICQ_EVENT_OUTGOING
;
53 icq_Packet
*icq_EventCreatePacket(icq_Event
*pbase
)
55 icq_Packet
*p
=icq_PacketNew();
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
);
68 void icq_EventParsePacket(icq_Event
*pevent
, icq_Packet
*p
)
70 /* parse header of tcp packet */
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 */
80 /* Message Event - extends generic Event */
82 icq_MessageEvent
*icq_CreateMessageEvent(int subtype
, unsigned long uin
,
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
);
90 pbase
->createPacket
=icq_MessageCreatePacket
;
93 pbase
->eventName
=icq_MessageEventName
;
94 pbase
->eventDump
=icq_MessageEventDump
;
100 void icq_MessageEventInit(icq_MessageEvent
*p
, int type
, int subtype
,
101 unsigned long uin
, int msgtype
, const char *message
)
103 icq_EventInit((icq_Event
*)p
, type
, subtype
, uin
, ICQ_TCP_VER
);
105 p
->message
=(char *)message
;
106 p
->status
=0; /* FIXME */
109 icq_Packet
*icq_MessageCreatePacket(icq_Event
*pbase
, icq_TCPLink
*plink
)
111 icq_MessageEvent
*pevent
=(icq_MessageEvent
*)pbase
;
114 icq_Packet
*p
=icq_EventCreatePacket(pbase
);
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
);
129 void icq_MessageParsePacket(icq_Event
*pbase
, icq_Packet
*p
)
131 icq_MessageEvent
*pevent
=(icq_MessageEvent
*)pbase
;
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 */
144 const char *icq_MessageEventName(icq_Event
*p
)
146 if (p
->type
==ICQ_EVENT_MESSAGE
)
148 else if (p
->type
==ICQ_EVENT_ACK
)
149 return "message ack";
151 return "message cancel";
154 const char *icq_MessageEventDump(icq_Event
*p
)
156 static char buf
[255];
157 icq_MessageEvent
*pevent
=(icq_MessageEvent
*)p
;
159 sprintf(buf
, ", type=%x, message=\"%10s...\", status=%x",
160 pevent
->type
, pevent
->message
, pevent
->status
);
166 /* URL Event - extends message Event */
168 icq_URLEvent
*icq_CreateURLEvent(int subtype
, unsigned long uin
,
169 const char *message
, const char *url
)
171 char *str
=(char *)malloc(strlen(message
)+strlen(url
)+2);
175 strcpy((char*)str
, message
);
176 *(str
+strlen(message
))=0xFE;
177 strcpy((char*)(str
+strlen(message
)+1), url
);
179 /* TODO: make sure create message event copies message */
180 pbase
=(icq_Event
*)icq_CreateMessageEvent(subtype
, uin
, str
);
181 p
=(icq_URLEvent
*)pbase
;
185 *(p
->message
+strlen(message
))=0x00;
186 p
->url
=p
->message
+strlen(message
)+1;
188 pbase
->createPacket
=icq_URLCreatePacket
;
191 pbase
->eventName
=icq_URLEventName
;
192 pbase
->eventDump
=icq_URLEventDump
;
199 icq_Packet
*icq_URLCreatePacket(icq_Event
*pbase
, icq_TCPLink
*plink
)
201 icq_URLEvent
*pevent
=(icq_URLEvent
*)pbase
;
204 /* hack message string to include url */
205 *(pevent
->message
+strlen(pevent
->message
))=0xFE;
208 p
=icq_MessageCreatePacket(pbase
, plink
);
210 /* hack message string to seperate url */
211 *(pevent
->message
+strlen(pevent
->message
))=0x00;
216 void icq_URLParsePacket(icq_Event
*pbase
, icq_Packet
*p
)
219 icq_URLEvent
*pevent
=(icq_URLEvent
*)pbase
;
221 /* TODO: make sure messageparsepacket allocates message string
222 * and add a delete event function */
223 icq_MessageParsePacket(pbase
, p
);
225 /* hack message string to seperate url */
226 pfe
=strchr(pevent
->message
, '\xFE');
235 const char *icq_URLEventName(icq_Event
*p
)
237 if (p
->type
==ICQ_EVENT_MESSAGE
)
239 else if (p
->type
==ICQ_EVENT_ACK
)
245 const char *icq_URLEventDump(icq_Event
*p
)
247 static char buf
[255];
248 icq_MessageEvent
*pevent
=(icq_MessageEvent
*)p
;
250 sprintf(buf
, ", type=%x, message=\"%10s...\", url=\"%10s...\" status=%x",
251 pevent
->type
, pevent
->message
, pevent
->url
, pevent
->status
);
258 /* Chat Request Event - extends Message Event */
260 icq_ChatRequestEvent
*icq_ChatRequestEventNew(int subtype
,
261 unsigned long uin
, const char *message
, int port
)
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
);
269 pbase
->createPacket
=icq_ChatRequestCreatePacket
;
272 pbase
->eventName
=icq_ChatRequestEventName
;
273 pbase
->eventDump
=icq_ChatRequestEventDump
;
279 icq_Packet
*icq_ChatRequestCreatePacket(icq_Event
*pbase
,
282 icq_ChatRequestEvent
*pevent
=(icq_ChatRequestEvent
*)pbase
;
284 /* create header and message data */
285 icq_Packet
*p
=icq_MessageCreatePacket(pbase
, plink
);
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
));
295 void icq_ChatParsePacket(icq_Event
*pbase
, icq_Packet
*p
)
297 icq_ChatRequestEvent
*pevent
=(icq_ChatRequestEvent
*)pbase
;
300 /* parse header and message event data */
301 icq_MessageParsePacket(pbase
, p
);
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 */
308 pevent
->port
=ntohl(port
);
312 const char *icq_ChatRequestEventName(icq_Event
*p
)
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";
321 return "chat request ack";
322 } else if (p
->type
==ICQ_EVENT_CANCEL
)
323 return "chat request cancel";
325 return "unknown chat request";
328 const char *icq_ChatRequestEventDump(icq_Event
*p
)
330 static char buf
[255];
331 static char buf2
[255];
332 icq_ChatRequestEvent
*pevent
=(icq_ChatRequestEvent
*)p
;
334 strcpy(buf
, icq_MessageEventDump(p
));
335 sprintf(buf2
, ", port=%d", pevent
->port
);
342 /* File Request Event - builds on Message Event */
344 icq_FileRequestEvent
*icq_FileRequestEventNew(int subtype
,
345 unsigned long uin
, const char *message
, const char *filename
,
346 unsigned long filesize
)
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
;
355 pbase
->createPacket
=icq_FileRequestCreatePacket
;
358 pbase
->eventName
=icq_FileRequestEventName
;
359 pbase
->eventDump
=icq_FileRequestEventDump
;
365 icq_Packet
*icq_FileRequestCreatePacket(icq_Event
*pbase
,
368 icq_FileRequestEvent
*pevent
=(icq_FileRequestEvent
*)pbase
;
370 /* create header and message data */
371 icq_Packet
*p
=icq_MessageCreatePacket(pbase
, plink
);
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
));
382 void icq_FileParsePacket(icq_Event
*pbase
, icq_Packet
*p
)
384 icq_FileRequestEvent
*pevent
=(icq_FileRequestEvent
*)pbase
;
386 /* parse header and message data */
387 icq_MessageParsePacket(pbase
, p
);
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 */
397 const char *icq_FileRequestEventName(icq_Event
*p
)
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";
406 return "file request ack";
407 } else if (p
->type
==ICQ_EVENT_CANCEL
)
408 return "file request cancel";
410 return "unknown file request";
413 const char *icq_FileRequestEventDump(icq_Event
*p
)
415 static char buf
[255];
416 static char buf2
[255];
417 icq_FileRequestEvent
*pevent
=(icq_FileRequestEvent
*)p
;
419 strcpy(buf
, icq_MessageEventDump(p
));
420 sprintf(buf2
, ", port=%d, filename=\"%s\", filesize=%ld", pevent
->port
,
421 pevent
->filename
, pevent
->filesize
);
428 /* main packet parser */
430 icq_Event
*icq_ParsePacket(icq_Packet
*p
)
433 icq_Event
*pevent
=(icq_Event
*)malloc(sizeof(icq_FileRequestEvent
));
434 pevent
->direction
=ICQ_EVENT_INCOMING
;
435 pevent
->time
=time(0);
437 icq_EventParsePacket(pevent
, p
);
439 switch(pevent
->type
) {
441 case ICQ_TCP_MSG_MSG
:
442 icq_MessageParsePacket(pevent
, p
);
444 case ICQ_TCP_MSG_URL
:
445 icq_URLParsePacket(pevent
, p
);
447 case ICQ_TCP_MSG_CHAT
:
448 icq_ChatParsePacket(pevent
, p
);
450 case ICQ_TCP_MSG_FILE
:
451 icq_FileParsePacket(pevent
, p
);
460 /* FIXME: ensure no bytes are remaining */
466 const char *icq_EventDump(icq_Event
*pevent
)
468 static char buf
[255];
470 sprintf("%s event sent to uin %ld { %s }", (pevent
->eventName
)(pevent
),
471 pevent
->uin
, (pevent
->eventDump
)(pevent
) );