1 
2 
3 /*
4  * Assemble outgoing and dissect incoming packets.
5  *
6  * climm Copyright (C) © 2001-2007 Rüdiger Kuhlmann
7  *
8  * climm is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 dated June, 1991.
11  *
12  * climm is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15  * License for more details.
16  *
17  * In addition, as a special exception permission is granted to link the
18  * code of this release of climm with the OpenSSL project's "OpenSSL"
19  * library, and distribute the linked executables.  You must obey the GNU
20  * General Public License in all respects for all of the code used other
21  * than "OpenSSL".  If you modify this file, you may extend this exception
22  * to your version of the file, but you are not obligated to do so.  If you
23  * do not wish to do so, delete this exception statement from your version
24  * of this file.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this package; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
29  * 02111-1307, USA.
30  *
31  * $Id: packet.c 2770 2009-04-01 16:26:43Z kuhlmann $
32  *
33  * Note: alle read strings need to be free()ed.
34  */
35 
36 #include "climm.h"
37 #include "packet.h"
38 #include "preferences.h"
39 #include "util_ui.h"
40 #include "contact.h"
41 #include "buildmark.h"
42 #include <assert.h>
43 
44 #define cap_id   "\x82\x22\x44\x45\x53\x54\x00\x00"
45 #define cap_none "\x00\x00\x00\x00\x00\x00\x00\x00"
46 #define cap_str  "\xbc\xd2\x00\x04\xac\x96\xdd\x96"
47 
48 #define cap_mid  "\x4c\x7f\x11\xd1"
49 #define cap_mstr "\x4f\xe9\xd3\x11"
50 #define cap_aim  "\x09\x46\x13"
51 
52 static Cap caps[CAP_MAX] =
53 {
54     { CAP_NONE,        16, cap_none cap_none,                   "CAP_NONE",        NULL },
55     /* AIM capabilities */
56     { CAP_AIM_VOICE,   16, cap_aim "\x41" cap_mid cap_id,       "CAP_AIM_VOICE",   NULL },
57     { CAP_AIM_SFILE,   16, cap_aim "\x43" cap_mid cap_id,       "CAP_AIM_SFILE",   NULL },
58     { CAP_REVCONNREQ,  16, cap_aim "\x44" cap_mid cap_id,       "CAP_REVCONNREQ",  NULL },
59     { CAP_AIM_IMIMAGE, 16, cap_aim "\x45" cap_mid cap_id,       "CAP_AIM_IMIMAGE", NULL },
60     { CAP_AIM_BUDICON, 16, cap_aim "\x46" cap_mid cap_id,       "CAP_AIM_BUDICON", NULL },
61     { CAP_AIM_STOCKS,  16, cap_aim "\x47" cap_mid cap_id,       "CAP_AIM_STOCKS",  NULL },
62     { CAP_AIM_GETFILE, 16, cap_aim "\x48" cap_mid cap_id,       "CAP_AIM_GETFILE", NULL },
63     { CAP_SRVRELAY,    16, cap_aim "\x49" cap_mid cap_id,       "CAP_SRVRELAY",    NULL },
64     { CAP_AIM_GAMES,   16, cap_aim "\x4a" cap_mid cap_id,       "CAP_AIM_GAMES",   NULL },
65     { CAP_AIM_SBUD,    16, cap_aim "\x4b" cap_mid cap_id,       "CAP_AIM_SBUD",    NULL },
66     { CAP_AIM_INTER,   16, cap_aim "\x4d" cap_mid cap_id,       "CAP_AIM_INTER",   NULL },
67     { CAP_AVATAR,      16, cap_aim "\x4c" cap_mid cap_id,       "CAP_AVATAR",      NULL },
68     { CAP_UTF8,        16, cap_aim "\x4e" cap_mid cap_id,       "CAP_UTF8",        NULL },
69     /* ICQ capabilities */
70     { CAP_RTFMSGS,     16, "\x97\xb1\x27\x51\x24\x3c\x43\x34\xad\x22\xd6\xab\xf7\x3f\x14\x92", "CAP_RTFMSGS",     NULL },
71     { CAP_IS_2001,     16, "\x2e\x7a\x64\x75\xfa\xdf\x4d\xc8\x88\x6f\xea\x35\x95\xfd\xb6\xdf", "CAP_IS_2001",     NULL },
72     { CAP_STR_2001,    16, "\xa0\xe9\x3f\x37" cap_mstr cap_str, "CAP_STR_2001",    NULL }, /* PSIG_INFO_PLUGIN_s   PMSG_QUERY_INFO_s */
73     { CAP_STR_2002,    16, "\x10\xcf\x40\xd1" cap_mstr cap_str, "CAP_STR_2002",    NULL }, /* PSIG_STATUS_PLUGIN_s PMSG_QUERY_STATUS_s */
74     { CAP_AIM_CHAT,    16, "\x74\x8f\x24\x20\x62\x87\x11\xd1" cap_id,                          "CAP_AIM_CHAT",    NULL },
75     { CAP_TYPING,      16, "\x56\x3f\xc8\x09\x0b\x6f\x41\xbd\x9f\x79\x42\x26\x09\xdf\xa2\xf3", "CAP_TYPING",      NULL },
76     { CAP_XTRAZ,       16, "\x1a\x09\x3c\x6c\xd7\xfd\x4e\xc5\x9d\x51\xa6\x47\x4e\x34\xf5\xa0", "CAP_XTRAZ", NULL },
77     /* client detection capabilities */
78     { CAP_TRILL_CRYPT, 16, "\xf2\xe7\xc7\xf4\xfe\xad\x4d\xfb\xb2\x35\x36\x79\x8b\xdf\x00\x00", "CAP_TRILL_CRYPT", NULL },
79     { CAP_TRILL_2,     16, "\x97\xb1\x27\x51\x24\x3c\x43\x34\xad\x22\xd6\xab\xf7\x3f\x14\x09", "CAP_TRILL_2",     NULL },
80     { CAP_LICQ,        16, "\x09\x49\x13\x49" cap_mid cap_id,   "CAP_LICQ",        NULL },
81     { CAP_LICQNEW,     12, "Licq client \x00\x00\x00\x00",      "CAP_LICQNEW",     NULL },
82     { CAP_SIM,         15, "\x97\xb1\x27\x51\x24\x3c\x43\x34\xad\x22\xd6\xab\xf7\x3f\x14\x48", "CAP_SIM",         NULL },
83     { CAP_SIMNEW,      12, "SIM client  \x00\x00\x00\x00",      "CAP_SIMNEW",      NULL },
84     { CAP_MACICQ,      16, "\xdd\x16\xf2\x02\x84\xe6\x11\xd4\x90\xdb\x00\x10\x4b\x9b\x4b\x7d", "CAP_MACICQ",      NULL },
85     { CAP_CLIMM,       12, "climm\xa9 R.K. \x00\x00\x00\x00",   "CAP_CLIMM",       NULL },
86     { CAP_MICQ,        12, "mICQ \xa9 R.K. \x00\x00\x00\x00",   "CAP_MICQ",        NULL },
87     { CAP_KXICQ,       16, "\x09\x49\x13\x44" cap_mid cap_id,   "CAP_KXICQ",       NULL },
88     { CAP_KOPETE,      12, "Kopete ICQ  \x00\x00\x00\x00",      "CAP_KOPETE",      NULL },
89     { CAP_IMSECURE,    12, "IMsecureCphr\x00\x00\x00\x00",      "CAP_IMSECURE",    NULL },
90     { CAP_ARQ,          9, "&RQinside\x00\x00\x00\x00\x00\x00\x00", "CAP_ARQ",     NULL },
91     { CAP_MIRANDA,      8, "MirandaM\x00\x00\x00\x00\x00\x00\x00\x00", "CAP_MIRANDA", NULL },
92     { CAP_QIP,         16, "\x56\x3f\xc8\x09\x0b\x6f\x41QIP 2005a", "CAP_QIP",     NULL },
93     { CAP_IM2,         16, "\x74\xed\xc3\x36\x44\xdf\x48\x5b\x8b\x1c\x67\x1a\x1f\x86\x09\x9f", "CAP_IM2", NULL },
94     /* Unknown capabilities */
95     { CAP_UTF8ii,      16, cap_aim "\x4e" cap_mid "\x82\x22\x44\x45\x53\x54ii", "CAP_UTF82", NULL },
96     { CAP_WIERD1,      16, "\x17\x8c\x2d\x9b\xda\xa5\x45\xbb\x8d\xdb\xf3\xbd\xbd\x53\xa1\x0a", "CAP_WIERD1", NULL },
97     { CAP_WIERD3,      16, "\x67\x36\x15\x15\x61\x2d\x4c\x07\x8f\x3d\xbd\xe6\x40\x8e\xa0\x41", "CAP_WIERD3", NULL },
98     { CAP_WIERD4,      16, "\xe3\x62\xc1\xe9\x12\x1a\x4b\x94\xa6\x26\x7a\x74\xde\x24\x27\x0d", "CAP_WIERD4", NULL },
99     { CAP_WIERD5,      16, "\xb9\x97\x08\xb5\x3a\x92\x42\x02\xb0\x69\xf1\xe7\x57\xbb\x2e\x17", "CAP_WIERD5", NULL },
100     { CAP_WIERD7,      16, "\xb6\x07\x43\x78\xf5\x0c\x4a\xc7\x90\x92\x59\x38\x50\x2d\x05\x91", "CAP_WIERD7", NULL },
101     { CAP_11,          16, "\x01\x01\x01\x01\x01\x01\x19\x04\x4a\x16\xed\x79\x2c\xb1\x71\x01", "CAP_11", NULL },
102     { CAP_12,          16, "\x02\x02\x02\x02\x02\x02\xb3\xf8\x53\x44\x7f\x0d\x2d\x83\xbd\x76", "CAP_12", NULL },
103 
104     { 0, 0, NULL, NULL, NULL }
105 };
106 
107 static str_s packetstr[] =
108 {
109     { NULL, 0, 0 },
110     { NULL, 0, 0 },
111     { NULL, 0, 0 },
112     { NULL, 0, 0 },
113     { "<invalidlen>", 12, 0 },
114     { "", 0, 0 },
115 };
116 
117 static int packetstrind = 0;
118 
119 #define PACKETMAXSTR 4
120 #define PACKETSTRINVALID 4
121 #define PACKETSTREMPTY 5
122 
123 #undef PacketC
PacketC(DEBUG0PARAM)124 Packet *PacketC (DEBUG0PARAM)
125 {
126     Packet *pak;
127 
128     pak = calloc (1, sizeof (Packet));
129     assert (pak);
130 
131     Debug (DEB_PACKET, "<--- %p new", pak);
132     uiG.packets++;
133 
134     return pak;
135 }
136 
137 #undef PacketCreate
PacketCreate(str_t str DEBUGPARAM)138 Packet *PacketCreate (str_t str DEBUGPARAM)
139 {
140     Packet *newpak;
141 
142     newpak = calloc (1, sizeof (Packet));
143     assert (newpak);
144 
145     memcpy (newpak->data, str->txt, str->len);
146     newpak->len = str->len;
147 
148     Debug (DEB_PACKET, "<-+- %p create", newpak);
149     uiG.packets++;
150 
151     return newpak;
152 }
153 
154 #undef PacketD
PacketD(Packet * pak DEBUGPARAM)155 void PacketD (Packet *pak DEBUGPARAM)
156 {
157     Debug (DEB_PACKET, "---> %p free", pak);
158     uiG.packets--;
159     free (pak);
160 }
161 
162 #undef PacketClone
PacketClone(const Packet * pak DEBUGPARAM)163 Packet *PacketClone (const Packet *pak DEBUGPARAM)
164 {
165     Packet *newpak;
166 
167     newpak = malloc (sizeof (Packet));
168     assert (newpak);
169 
170     memcpy (newpak, pak, sizeof (Packet));
171     newpak->rpos = 0;
172 
173     Debug (DEB_PACKET, "<-+- %p clone %p", newpak, pak);
174     uiG.packets++;
175 
176     return newpak;
177 }
178 
PacketWrite1(Packet * pak,UBYTE data)179 void PacketWrite1 (Packet *pak, UBYTE data)
180 {
181     assert (pak);
182     assert (pak->wpos < PacketMaxData);
183 
184     pak->data[pak->wpos++] = data;
185     if (pak->wpos > pak->len)
186         pak->len = pak->wpos;
187 }
188 
PacketWrite2(Packet * pak,UWORD data)189 void PacketWrite2 (Packet *pak, UWORD data)
190 {
191     assert (pak);
192     assert (pak->wpos + 1 < PacketMaxData);
193 
194     pak->data[pak->wpos++] = data & 0xff;  data >>= 8;
195     pak->data[pak->wpos++] = data;
196     if (pak->wpos > pak->len)
197         pak->len = pak->wpos;
198 }
199 
PacketWriteB2(Packet * pak,UWORD data)200 void PacketWriteB2 (Packet *pak, UWORD data)
201 {
202     assert (pak);
203     assert (pak->wpos + 1 < PacketMaxData);
204 
205     pak->data[pak->wpos++] = data >> 8;
206     pak->data[pak->wpos++] = data & 0xff;
207     if (pak->wpos > pak->len)
208         pak->len = pak->wpos;
209 }
210 
PacketWrite4(Packet * pak,UDWORD data)211 void PacketWrite4 (Packet *pak, UDWORD data)
212 {
213     assert (pak);
214     assert (pak->wpos + 3 < PacketMaxData);
215 
216     pak->data[pak->wpos++] = data & 0xff;  data >>= 8;
217     pak->data[pak->wpos++] = data & 0xff;  data >>= 8;
218     pak->data[pak->wpos++] = data & 0xff;  data >>= 8;
219     pak->data[pak->wpos++] = data;
220     if (pak->wpos > pak->len)
221         pak->len = pak->wpos;
222 }
223 
PacketWriteB4(Packet * pak,UDWORD data)224 void PacketWriteB4 (Packet *pak, UDWORD data)
225 {
226     assert (pak);
227     assert (pak->wpos + 3 < PacketMaxData);
228 
229     pak->data[pak->wpos++] =  data >> 24;
230     pak->data[pak->wpos++] = (data >> 16) & 0xff;
231     pak->data[pak->wpos++] = (data >>  8) & 0xff;
232     pak->data[pak->wpos++] =  data        & 0xff;
233     if (pak->wpos > pak->len)
234         pak->len = pak->wpos;
235 }
236 
PacketWriteCapID(Packet * pak,UBYTE id)237 void PacketWriteCapID (Packet *pak, UBYTE id)
238 {
239     UBYTE i;
240 
241     assert (pak);
242     assert (id < CAP_MAX);
243 
244     if (caps[id].id == id)
245     {
246         if (id == CAP_CLIMM || id == CAP_MICQ)
247         {
248             PacketWriteData (pak, (const char *)caps[id].cap, 12);
249             PacketWriteB4   (pak, BuildVersionNum);
250         }
251         else
252             PacketWriteData (pak, (const char *)caps[id].cap, 16);
253         return;
254     }
255 
256     for (i = 0; i < CAP_MAX; i++)
257         if (caps[i].id == id)
258             break;
259 
260     i %= CAP_MAX;
261     PacketWriteData (pak, (const char *)caps[i].cap, 16);
262 }
263 
PacketWriteCap(Packet * pak,Cap * cap)264 void PacketWriteCap (Packet *pak, Cap *cap)
265 {
266     assert (pak);
267     assert (cap);
268 
269     PacketWriteData (pak, (cap->var ? (const char *)cap->var : cap->cap), 16);
270 }
271 
PacketWriteData(Packet * pak,const char * data,UWORD len)272 void PacketWriteData (Packet *pak, const char *data, UWORD len)
273 {
274     assert (pak);
275     assert (pak->wpos + len < PacketMaxData);
276 
277     memcpy (pak->data + pak->wpos, data, len);
278     pak->wpos += len;
279     if (pak->wpos > pak->len)
280         pak->len = pak->wpos;
281 }
282 
PacketWriteStr(Packet * pak,const char * data)283 void PacketWriteStr(Packet *pak, const char *data)
284 {
285     if (data)
286         PacketWriteData (pak, data, strlen (data));
287 }
288 
PacketWriteLNTS(Packet * pak,const char * data)289 void PacketWriteLNTS (Packet *pak, const char *data)
290 {
291     data = data ? data : "";
292 
293     assert (pak);
294     assert (pak->wpos + 3 + strlen (data) < PacketMaxData);
295 
296     PacketWrite2 (pak, strlen (data) + 1);
297     PacketWriteData (pak, data, strlen (data));
298     PacketWrite1 (pak, 0);
299 }
300 
PacketWriteLNTS2(Packet * pak,str_t text)301 void PacketWriteLNTS2 (Packet *pak, str_t text)
302 {
303     int len = text ? text->len : 0;
304     char *data = text ? text->txt : "";
305 
306     assert (pak);
307     assert (pak->wpos + 3 + len < PacketMaxData);
308 
309     PacketWrite2 (pak, len + 1);
310     PacketWriteData (pak, data, len);
311     PacketWrite1 (pak, 0);
312 }
313 
PacketWriteDLStr(Packet * pak,const char * data)314 void PacketWriteDLStr (Packet *pak, const char *data)
315 {
316     data = data ? data : "";
317 
318     assert (pak);
319     assert (pak->wpos + 4 + strlen (data) < PacketMaxData);
320 
321     PacketWrite4 (pak, strlen (data));
322     PacketWriteData (pak, data, strlen (data));
323 }
324 
PacketWriteLLNTS(Packet * pak,const char * data)325 void PacketWriteLLNTS (Packet *pak, const char *data)
326 {
327     data = data ? data : "";
328 
329     assert (pak);
330     assert (pak->wpos + 5 + strlen (data) < PacketMaxData);
331 
332     PacketWrite2 (pak, strlen (data) + 3);
333     PacketWrite2 (pak, strlen (data) + 1);
334     PacketWriteData (pak, data, strlen (data));
335     PacketWrite1 (pak, 0);
336 }
337 
PacketWriteCont(Packet * pak,Contact * cont)338 void PacketWriteCont (Packet *pak, Contact *cont)
339 {
340     int len = strlen (cont->screen);
341     PacketWrite1 (pak, len);
342     PacketWriteData (pak, cont->screen, len);
343 }
344 
PacketWriteTLV(Packet * pak,UDWORD type)345 void PacketWriteTLV (Packet *pak, UDWORD type)
346 {
347     UWORD pos;
348 
349     PacketWriteB2 (pak, type);
350     pos = pak->wpos;
351     PacketWriteB2 (pak, pak->tpos); /* will be length */
352     pak->tpos = pos;
353 }
354 
PacketWriteTLVDone(Packet * pak)355 void PacketWriteTLVDone (Packet *pak)
356 {
357     UWORD pos;
358 
359     pos = PacketReadAtB2 (pak, pak->tpos);
360     PacketWriteAtB2 (pak, pak->tpos, pak->wpos - pak->tpos - 2);
361     pak->tpos = pos;
362 }
363 
PacketWriteLen(Packet * pak)364 void PacketWriteLen (Packet *pak)
365 {
366     UWORD pos;
367 
368     pos = pak->wpos;
369     PacketWriteB2 (pak, pak->tpos); /* will be length */
370     pak->tpos = pos;
371 }
372 
PacketWriteLenDone(Packet * pak)373 void PacketWriteLenDone (Packet *pak)
374 {
375     UWORD pos;
376 
377     pos = PacketReadAtB2 (pak, pak->tpos);
378     PacketWriteAt2 (pak, pak->tpos, pak->wpos - pak->tpos - 2);
379     pak->tpos = pos;
380 }
381 
PacketWriteBLenDone(Packet * pak)382 void PacketWriteBLenDone (Packet *pak)
383 {
384     UWORD pos;
385 
386     pos = PacketReadAtB2 (pak, pak->tpos);
387     PacketWriteAtB2 (pak, pak->tpos, pak->wpos - pak->tpos - 2);
388     pak->tpos = pos;
389 }
390 
PacketWriteLen4(Packet * pak)391 void PacketWriteLen4 (Packet *pak)
392 {
393     UWORD pos;
394 
395     pos = pak->wpos;
396     PacketWrite4 (pak, pak->tpos); /* will be length */
397     pak->tpos = pos;
398 }
399 
PacketWriteLen4Done(Packet * pak)400 void PacketWriteLen4Done (Packet *pak)
401 {
402     UWORD pos;
403 
404     pos = PacketReadAt4 (pak, pak->tpos);
405     PacketWriteAt4 (pak, pak->tpos, pak->wpos - pak->tpos - 4);
406     pak->tpos = pos;
407 }
408 
PacketWritePos(const Packet * pak)409 UWORD PacketWritePos (const Packet *pak)
410 {
411     return pak->wpos;
412 }
413 
PacketWriteAt1(Packet * pak,UWORD at,UBYTE data)414 void PacketWriteAt1 (Packet *pak, UWORD at, UBYTE data)
415 {
416     assert (pak);
417     assert (at < PacketMaxData);
418 
419     pak->data[at++] = data;
420     if (at > pak->len)
421         pak->len = at;
422 }
423 
PacketWriteAt2(Packet * pak,UWORD at,UWORD data)424 void PacketWriteAt2 (Packet *pak, UWORD at, UWORD data)
425 {
426     assert (pak);
427     assert (at + 1 < PacketMaxData);
428 
429     pak->data[at++] = data & 0xff;  data >>= 8;
430     pak->data[at++] = data;
431     if (at > pak->len)
432         pak->len = at;
433 }
434 
PacketWriteAtB2(Packet * pak,UWORD at,UWORD data)435 void PacketWriteAtB2 (Packet *pak, UWORD at, UWORD data)
436 {
437     assert (pak);
438     assert (at + 1 < PacketMaxData);
439 
440     pak->data[at++] = data >> 8;
441     pak->data[at++] = data & 0xff;
442     if (at > pak->len)
443         pak->len = at;
444 }
445 
PacketWriteAt4(Packet * pak,UWORD at,UDWORD data)446 void PacketWriteAt4 (Packet *pak, UWORD at, UDWORD data)
447 {
448     assert (pak);
449     assert (at + 3 < PacketMaxData);
450 
451     pak->data[at++] = data & 0xff;  data >>= 8;
452     pak->data[at++] = data & 0xff;  data >>= 8;
453     pak->data[at++] = data & 0xff;  data >>= 8;
454     pak->data[at++] = data;
455     if (at > pak->len)
456         pak->len = at;
457 }
458 
PacketWriteAtB4(Packet * pak,UWORD at,UDWORD data)459 void PacketWriteAtB4 (Packet *pak, UWORD at, UDWORD data)
460 {
461     assert (pak);
462     assert (at + 3 < PacketMaxData);
463 
464     pak->data[at++] =  data >> 24;
465     pak->data[at++] = (data >> 16) & 0xff;
466     pak->data[at++] = (data >>  8) & 0xff;
467     pak->data[at++] =  data        & 0xff;
468     if (at > pak->len)
469         pak->len = at;
470 }
471 
PacketRead1(Packet * pak)472 UBYTE PacketRead1 (Packet *pak)
473 {
474     assert (pak);
475 
476     if (pak->rpos + 1 > PacketMaxData)
477         return 0;
478 
479     return pak->data[pak->rpos++];
480 }
481 
PacketRead2(Packet * pak)482 UWORD PacketRead2 (Packet *pak)
483 {
484     UWORD data;
485 
486     assert (pak);
487 
488     if (pak->rpos + 2 > PacketMaxData)
489         return 0;
490 
491     data  = pak->data[pak->rpos++];
492     data |= pak->data[pak->rpos++] << 8;
493     return data;
494 }
495 
PacketReadB2(Packet * pak)496 UWORD PacketReadB2 (Packet *pak)
497 {
498     UWORD data;
499 
500     assert (pak);
501 
502     if (pak->rpos + 2 > PacketMaxData)
503         return 0;
504 
505     data  = pak->data[pak->rpos++] << 8;
506     data |= pak->data[pak->rpos++];
507     return data;
508 }
509 
PacketRead4(Packet * pak)510 UDWORD PacketRead4 (Packet *pak)
511 {
512     UDWORD data;
513 
514     assert (pak);
515 
516     if (pak->rpos + 4 > PacketMaxData)
517         return 0;
518 
519     data  = pak->data[pak->rpos++];
520     data |= pak->data[pak->rpos++] << 8;
521     data |= pak->data[pak->rpos++] << 16;
522     data |= pak->data[pak->rpos++] << 24;
523     return data;
524 }
525 
PacketReadB4(Packet * pak)526 UDWORD PacketReadB4 (Packet *pak)
527 {
528     UDWORD data;
529 
530     assert (pak);
531 
532     if (pak->rpos + 4 > PacketMaxData)
533         return 0;
534 
535     data  = pak->data[pak->rpos++] << 24;
536     data |= pak->data[pak->rpos++] << 16;
537     data |= pak->data[pak->rpos++] << 8;
538     data |= pak->data[pak->rpos++];
539     return data;
540 }
541 
PacketReadCap(Packet * pak)542 Cap *PacketReadCap (Packet *pak)
543 {
544     const UBYTE *cap;
545     UBYTE id;
546     char *p;
547 
548     assert (pak);
549 
550     if (pak->rpos + 16 > PacketMaxData)
551         return &caps[0];
552 
553     cap = pak->data + pak->rpos;
554     pak->rpos += 16;
555 
556     for (id = 0; id < CAP_MAX; id++)
557         if (caps[id].cap)
558         {
559 #ifdef HAVE_MEMCMP
560             if (!memcmp (cap, caps[id].cap, caps[id].len))
561             {
562                 if (caps[id].len != 16)
563                 {
564                     s_free (caps[id].var);
565                     caps[id].var = malloc (16);
566                     memcpy (caps[id].var, cap, 16);
567                 }
568                 return &caps[id];
569             }
570 #else
571             {
572                 const UBYTE *p, *q;
573                 int i;
574                 for (p = cap, q = caps[id].cap, i = 0; i < caps[id].len; i++)
575                     if (*p++ != *q++)
576                         break;
577                     else
578                         if (i + 1 == caps[id].len)
579                         {
580                             if (caps[id].len != 16)
581                             {
582                                 s_free ((char *)caps[id].var);
583                                 caps[id].var = malloc (16);
584                                 memcpy (caps[id].var, cap, 16);
585                             }
586                             return &caps[id];
587                         }
588             }
589 #endif
590         }
591         else
592             break;
593     if (id == CAP_MAX)
594         return &caps[0];
595 
596     p = malloc (16);
597     assert (p);
598     memcpy (p, cap, 16);
599 
600     caps[id].id = id;
601     caps[id].cap = p;
602     caps[id].len = 16;
603     caps[id].name = strdup (s_sprintf ("CAP_UNK_%d", id));
604     return &caps[id];
605 }
606 
PacketReadData(Packet * pak,str_t str,UWORD len)607 void PacketReadData (Packet *pak, str_t str, UWORD len)
608 {
609     assert (pak);
610 
611     if (pak->rpos + len > PacketMaxData)
612     {
613         if (str)
614         {
615             str->len = 0;
616             if (str->max)
617                 *str->txt = '\0';
618         }
619         return;
620     }
621     if (str)
622     {
623         s_init (str, "", len + 1);
624         if (str->max > len)
625         {
626             str->len = len;
627             str->txt[len] = '\0';
628             memcpy (str->txt, pak->data + pak->rpos, len);
629         }
630     }
631     pak->rpos += len;
632 }
633 
PacketReadB2Str(Packet * pak,str_t str)634 strc_t PacketReadB2Str (Packet *pak, str_t str)
635 {
636     unsigned int len;
637 
638     len = PacketReadB2 (pak);
639     if (pak->rpos + len >= PacketMaxData)
640     {
641         if (!str)
642             return &packetstr[PACKETSTRINVALID];
643         s_init (str, packetstr[PACKETSTRINVALID].txt, 0);
644         return str;
645     }
646 
647     if (!str)
648     {
649         packetstrind %= 4;
650         str = &packetstr[packetstrind++];
651     }
652 
653     s_init (str, "", len + 2);
654     assert (str->max >= len + 2);
655 
656     PacketReadData (pak, str, len);
657     str->txt[str->len = len] = '\0';
658 
659     return str;
660 }
661 
PacketReadL2Str(Packet * pak,str_t str)662 strc_t PacketReadL2Str (Packet *pak, str_t str)
663 {
664     unsigned int len;
665 
666     len = PacketRead2 (pak);
667     if (pak->rpos + len >= PacketMaxData)
668     {
669         if (!str)
670             return &packetstr[PACKETSTRINVALID];
671         s_init (str, packetstr[PACKETSTRINVALID].txt, 0);
672         return str;
673     }
674     if (!len)
675     {
676         if (!str)
677             return &packetstr[PACKETSTREMPTY];
678         s_init (str, "", 0);
679         return str;
680     }
681 
682     if (!str)
683     {
684         packetstrind %= 4;
685         str = &packetstr[packetstrind++];
686     }
687 
688     s_init (str, "", len + 2);
689     assert (str->max >= len + 2);
690 
691     PacketReadData (pak, str, len);
692     if (str->txt[len - 1])
693         str->txt[str->len = len] = '\0';
694     else
695         str->len = len - 1;
696     return str;
697 }
698 
PacketReadL4Str(Packet * pak,str_t str)699 strc_t PacketReadL4Str (Packet *pak, str_t str)
700 {
701     size_t len;
702 
703     len = PacketRead4 (pak);
704     if (pak->rpos + len >= PacketMaxData)
705     {
706         if (!str)
707             return &packetstr[PACKETSTRINVALID];
708         s_init (str, packetstr[PACKETSTRINVALID].txt, 0);
709         return str;
710     }
711 
712     if (!str)
713     {
714         packetstrind %= 4;
715         str = &packetstr[packetstrind++];
716     }
717 
718     s_init (str, "", len + 2);
719     assert (str->max >= len + 2);
720 
721     PacketReadData (pak, str, len);
722     str->txt[str->len = len] = '\0';
723 
724     return str;
725 }
726 
PacketReadUIN(Packet * pak)727 strc_t PacketReadUIN (Packet *pak)
728 {
729     UBYTE len = PacketRead1 (pak);
730     str_t str;
731 
732     packetstrind %= 4;
733     str = &packetstr[packetstrind++];
734     s_init (str, "", len + 2);
735     PacketReadData (pak, str, len);
736     str->txt[len] = '\0';
737     return str;
738 }
739 
PacketReadCont(Packet * pak,Server * serv)740 Contact *PacketReadCont (Packet *pak, Server *serv)
741 {
742     UBYTE len = PacketRead1 (pak);
743     Contact *cont;
744     str_s str = { NULL, 0, 0 };
745 
746     PacketReadData (pak, &str, len);
747     str.txt[len] = '\0';
748     cont = ContactScreen (serv, str.txt);
749     s_done (&str);
750     return cont;
751 }
752 
PacketReadPos(const Packet * pak)753 UWORD PacketReadPos (const Packet *pak)
754 {
755     return pak->rpos;
756 }
757 
PacketReadAt1(const Packet * pak,UWORD at)758 UBYTE PacketReadAt1 (const Packet *pak, UWORD at)
759 {
760     assert (pak);
761 
762     if (at + 1 > PacketMaxData)
763         return 0;
764 
765     return pak->data[at];
766 }
767 
PacketReadAt2(const Packet * pak,UWORD at)768 UWORD PacketReadAt2 (const Packet *pak, UWORD at)
769 {
770     UWORD data;
771 
772     assert (pak);
773 
774     if (at + 2 > PacketMaxData)
775         return 0;
776 
777     data  = pak->data[at++];
778     data |= pak->data[at] << 8;
779     return data;
780 }
781 
PacketReadAtB2(const Packet * pak,UWORD at)782 UWORD PacketReadAtB2 (const Packet *pak, UWORD at)
783 {
784     UWORD data;
785 
786     assert (pak);
787 
788     if (at + 2 > PacketMaxData)
789         return 0;
790 
791     data  = pak->data[at++] << 8;
792     data |= pak->data[at];
793     return data;
794 }
795 
PacketReadAt4(const Packet * pak,UWORD at)796 UDWORD PacketReadAt4 (const Packet *pak, UWORD at)
797 {
798     UDWORD data;
799 
800     assert (pak);
801 
802     if (at + 4 > PacketMaxData)
803         return 0;
804 
805     data  = pak->data[at++];
806     data |= pak->data[at++] << 8;
807     data |= pak->data[at++] << 16;
808     data |= pak->data[at] << 24;
809     return data;
810 }
811 
PacketReadAtB4(const Packet * pak,UWORD at)812 UDWORD PacketReadAtB4 (const Packet *pak, UWORD at)
813 {
814     UDWORD data;
815 
816     assert (pak);
817 
818     if (at + 4 > PacketMaxData)
819         return 0;
820 
821     data  = pak->data[at++] << 24;
822     data |= pak->data[at++] << 16;
823     data |= pak->data[at++] << 8;
824     data |= pak->data[at];
825     return data;
826 }
827 
PacketReadAtData(const Packet * pak,UWORD at,str_t str,UWORD len)828 void PacketReadAtData (const Packet *pak, UWORD at, str_t str, UWORD len)
829 {
830     assert (pak);
831 
832     if (at + len > PacketMaxData)
833     {
834         if (str)
835         {
836             str->len = 0;
837             if (str->max)
838                 *str->txt = '\0';
839         }
840         return;
841     }
842     if (str)
843     {
844         s_init (str, "", len + 1);
845         if (str->max > len)
846             memcpy (str->txt, pak->data + at, len);
847     }
848 }
849 
PacketReadAtL2Str(const Packet * pak,UWORD at,str_t str)850 strc_t PacketReadAtL2Str (const Packet *pak, UWORD at, str_t str)
851 {
852     unsigned int len;
853 
854     len = PacketReadAt2 (pak, at);
855     if (at + 2 + len >= PacketMaxData)
856     {
857         if (!str)
858             return &packetstr[PACKETSTRINVALID];
859         s_init (str, packetstr[PACKETSTRINVALID].txt, 0);
860         return str;
861     }
862     if (!len)
863     {
864         if (!str)
865             return &packetstr[PACKETSTREMPTY];
866         s_init (str, "", 0);
867         return str;
868     }
869 
870     if (!str)
871     {
872         packetstrind %= 4;
873         str = &packetstr[packetstrind++];
874     }
875 
876     s_init (str, "", len + 2);
877     assert (str->max >= len + 2);
878 
879     PacketReadAtData (pak, at + 2, str, len);
880     if (str->txt[len - 1])
881         str->txt[str->len = len] = '\0';
882     else
883         str->len = len - 1;
884 
885     return str;
886 }
887 
PacketReadLeft(const Packet * pak)888 int PacketReadLeft  (const Packet *pak)
889 {
890     if (pak->rpos > pak->len)
891         return 0;
892     return pak->len - pak->rpos;
893 }
894 
PacketCap(UBYTE id)895 Cap *PacketCap (UBYTE id)
896 {
897     if (id >= CAP_MAX)
898         return &caps[0];
899     return &caps[id];
900 }
901 
902