| |
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| |
2 /* |
| |
3 $Id: util.c 1162 2000-11-28 02:22:42Z warmenhoven $ |
| |
4 $Log$ |
| |
5 Revision 1.1 2000/11/28 02:22:42 warmenhoven |
| |
6 icq. whoop de doo |
| |
7 |
| |
8 Revision 1.32 2000/07/22 16:49:32 denis |
| |
9 Trinidad and Tobago country was added. |
| |
10 |
| |
11 Revision 1.31 2000/07/21 16:51:20 denis |
| |
12 All languages, possible in original icq were added. |
| |
13 Occupation array fixed. |
| |
14 |
| |
15 Revision 1.30 2000/07/20 09:58:59 denis |
| |
16 Occupation table corrected to comply with original ICQ. |
| |
17 |
| |
18 Revision 1.29 2000/07/04 07:25:29 pcadach |
| |
19 icq_FmtLog() crashed when it receives NULL at link argument. |
| |
20 |
| |
21 Revision 1.28 2000/06/30 13:59:43 denis |
| |
22 Slovak Republic country code fixed. |
| |
23 |
| |
24 Revision 1.27 2000/06/25 17:00:32 denis |
| |
25 icq_MetaOccupation[], icq_MetaPastBackgrounds[], |
| |
26 icq_MetaAffiliations[] and icq_MetaLanguages[] arrays were added along |
| |
27 with icq_GetMetaOccupationName(), icq_GetMetaBackgroundName(), |
| |
28 icq_GetMetaAffiliationName() and icq_GetMetaLanguageName() functions |
| |
29 to access them. |
| |
30 |
| |
31 Revision 1.26 2000/05/21 17:42:51 denis |
| |
32 Bulgaria country code was added. Thanks to |
| |
33 "Napalm Death" <napalmbox@hotmail.com> |
| |
34 |
| |
35 Revision 1.25 2000/05/03 18:29:15 denis |
| |
36 Callbacks have been moved to the ICQLINK structure. |
| |
37 |
| |
38 Revision 1.24 2000/04/10 16:36:04 denis |
| |
39 Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> |
| |
40 |
| |
41 Revision 1.23 2000/04/05 14:37:02 denis |
| |
42 Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 |
| |
43 compatibility. |
| |
44 |
| |
45 Revision 1.22 2000/03/31 12:49:15 nofate |
| |
46 remove static variable |
| |
47 |
| |
48 Revision 1.21 1999/11/11 15:10:33 guruz |
| |
49 - Added Base for Webpager Messages. Please type "make fixme" |
| |
50 - Removed Segfault when kicq is started the first time |
| |
51 |
| |
52 Revision 1.20 1999/10/07 18:01:40 denis |
| |
53 Cleanups. |
| |
54 |
| |
55 Revision 1.19 1999/09/29 17:16:45 denis |
| |
56 Cleanups. |
| |
57 |
| |
58 Revision 1.18 1999/07/18 20:24:27 bills |
| |
59 removed old byte order and contact list functions |
| |
60 |
| |
61 Revision 1.17 1999/07/16 15:46:03 denis |
| |
62 Cleaned up. |
| |
63 |
| |
64 Revision 1.16 1999/07/16 12:04:49 denis |
| |
65 Status support changed. |
| |
66 |
| |
67 Revision 1.15 1999/07/12 15:13:46 cproch |
| |
68 - added definition of ICQLINK to hold session-specific global variabled |
| |
69 applications which have more than one connection are now possible |
| |
70 - changed nearly every function defintion to support ICQLINK parameter |
| |
71 |
| |
72 Revision 1.14 1999/04/17 19:20:35 bills |
| |
73 removed *_link entries from icq_ContactItem, including cleanup/init code |
| |
74 |
| |
75 Revision 1.13 1999/04/14 15:06:51 denis |
| |
76 Cleanups for "strict" compiling (-ansi -pedantic) |
| |
77 |
| |
78 */ |
| |
79 |
| |
80 #include <stdlib.h> |
| |
81 #include <ctype.h> |
| |
82 |
| |
83 #ifndef _WIN32 |
| |
84 #include <unistd.h> |
| |
85 #endif |
| |
86 |
| |
87 #include "icqtypes.h" |
| |
88 #include "icq.h" |
| |
89 #include "icqlib.h" |
| |
90 #include "stdpackets.h" |
| |
91 #include "util.h" |
| |
92 #include "stdarg.h" |
| |
93 |
| |
94 /* |
| |
95 * This list of countries should be sorted according to country code. |
| |
96 * When adding new country, please preserve the order! |
| |
97 */ |
| |
98 icq_ArrayType icq_Countries[] = { |
| |
99 {"USA",1}, |
| |
100 {"Russia",7}, |
| |
101 {"Egypt",20}, |
| |
102 {"South Africa",27}, |
| |
103 {"Greece",30}, |
| |
104 {"Netherlands",31}, |
| |
105 {"Belgium",32}, |
| |
106 {"France",33}, |
| |
107 {"Monaco",33}, |
| |
108 {"Spain",34}, |
| |
109 {"Hungary",36}, |
| |
110 {"Yugoslavia",38}, |
| |
111 {"Italy",39}, |
| |
112 {"San Marino",39}, |
| |
113 {"Vatican City",39}, |
| |
114 {"Romania",40}, |
| |
115 {"Liechtenstein",41}, |
| |
116 {"Switzerland",41}, |
| |
117 {"Czech Republic",42}, |
| |
118 {"Austria",43}, |
| |
119 {"UK",44}, |
| |
120 {"Denmark",45}, |
| |
121 {"Sweden",46}, |
| |
122 {"Norway",47}, |
| |
123 {"Poland",48}, |
| |
124 {"Germany",49}, |
| |
125 {"Peru",51}, |
| |
126 {"Mexico",52}, |
| |
127 {"Guantanomo Bay",53}, |
| |
128 {"Argentina",54}, |
| |
129 {"Brazil",55}, |
| |
130 {"Chile",56}, |
| |
131 {"Columbia",57}, |
| |
132 {"Venezuela",58}, |
| |
133 {"Malaysia",60}, |
| |
134 {"Australia",61}, |
| |
135 {"Indonesia",62}, |
| |
136 {"Philippines",63}, |
| |
137 {"New Zealand",64}, |
| |
138 {"Singapore",65}, |
| |
139 {"Thailand",66}, |
| |
140 {"Japan",81}, |
| |
141 {"South Korea",82}, |
| |
142 {"Vietnam",84}, |
| |
143 {"China",86}, |
| |
144 {"Turkey",90}, |
| |
145 {"India",91}, |
| |
146 {"Pakistan",92}, |
| |
147 {"Sri Lanka",94}, |
| |
148 {"Iran",98}, |
| |
149 {"Canada",107}, |
| |
150 {"Morocco",212}, |
| |
151 {"Algeria",213}, |
| |
152 {"Tunisia",216}, |
| |
153 {"Libya",218}, |
| |
154 {"Senegal",221}, |
| |
155 {"Mali",223}, |
| |
156 {"Ivory Coast",225}, |
| |
157 {"Liberia",231}, |
| |
158 {"Ghana",233}, |
| |
159 {"Nigeria",234}, |
| |
160 {"Cameroon",237}, |
| |
161 {"Gabon",241}, |
| |
162 {"Zaire",243}, |
| |
163 {"Ethiopia",251}, |
| |
164 {"Kenya",254}, |
| |
165 {"Tanzania",255}, |
| |
166 {"Zimbabwe",263}, |
| |
167 {"Namibia",264}, |
| |
168 {"Malawi",265}, |
| |
169 {"Aruba",297}, |
| |
170 {"Portugal",351}, |
| |
171 {"Luxembourg",352}, |
| |
172 {"Ireland",353}, |
| |
173 {"Iceland",354}, |
| |
174 {"Malta",356}, |
| |
175 {"Cyprus",357}, |
| |
176 {"Finland",358}, |
| |
177 {"Bulgaria",359}, |
| |
178 {"Ukraine",380}, |
| |
179 {"Belize",501}, |
| |
180 {"Guatemala",502}, |
| |
181 {"El Salvador",503}, |
| |
182 {"Honduras",504}, |
| |
183 {"Nicaragua",505}, |
| |
184 {"Costa Rice",506}, |
| |
185 {"Panama",507}, |
| |
186 {"Haiti",509}, |
| |
187 {"Guadeloupe",590}, |
| |
188 {"Bolivia",591}, |
| |
189 {"Guyana",592}, |
| |
190 {"Ecuador",593}, |
| |
191 {"Paraguay",595}, |
| |
192 {"French Antilles",596}, |
| |
193 {"Suriname",597}, |
| |
194 {"Uruguay",598}, |
| |
195 {"Netherlands Antilles",599}, |
| |
196 {"Saipan",670}, |
| |
197 {"Saipan",670}, |
| |
198 {"Guam",671}, |
| |
199 {"Papua New Guinea",675}, |
| |
200 {"Fiji",679}, |
| |
201 {"American Samoa",684}, |
| |
202 {"New Caledonia",687}, |
| |
203 {"French Polynesia",689}, |
| |
204 {"Hong Kong",852}, |
| |
205 {"Trinidad and Tobago",868}, |
| |
206 {"Bangladesh",880}, |
| |
207 {"Taiwan",886}, |
| |
208 {"Jordan",962}, |
| |
209 {"Iraq",964}, |
| |
210 {"Kuwait",965}, |
| |
211 {"Saudia Arabia",966}, |
| |
212 {"Yemen",967}, |
| |
213 {"Oman",968}, |
| |
214 {"United Arab Emirates",971}, |
| |
215 {"Israel",972}, |
| |
216 {"Bahrain",973}, |
| |
217 {"Qatar",974}, |
| |
218 {"Nepal",977}, |
| |
219 {"Slovak Republic",4201}, |
| |
220 {"Not entered",0xffff}, |
| |
221 }; |
| |
222 |
| |
223 icq_ArrayType icq_MetaOccupation[] = { |
| |
224 {"Academic", 1}, |
| |
225 {"Administrative", 2}, |
| |
226 {"Art/Entertainment", 3}, |
| |
227 {"College Student", 4}, |
| |
228 {"Computers", 5}, |
| |
229 {"Community & Social", 6}, |
| |
230 {"Education", 7}, |
| |
231 {"Engineering", 8}, |
| |
232 {"Financial Services", 9}, |
| |
233 {"Government", 10}, |
| |
234 {"High School Student", 11}, |
| |
235 {"Home", 12}, |
| |
236 {"ICQ - Providing Help", 13}, |
| |
237 {"Law", 14}, |
| |
238 {"Managerial", 15}, |
| |
239 {"Manufacturing", 16}, |
| |
240 {"Medical/Health", 17}, |
| |
241 {"Military", 18}, |
| |
242 {"Non-Government Organization", 19}, |
| |
243 {"Professional", 20}, |
| |
244 {"Retail", 21}, |
| |
245 {"Retired", 22}, |
| |
246 {"Science & Research", 23}, |
| |
247 {"Sports", 24}, |
| |
248 {"Technical", 25}, |
| |
249 {"University Student", 26}, |
| |
250 {"Web Building", 27}, |
| |
251 {"Other Services", 99}, |
| |
252 }; |
| |
253 |
| |
254 icq_ArrayType icq_MetaPastBackgrounds[] = { |
| |
255 {"Elementary School", 300}, |
| |
256 {"High School", 301}, |
| |
257 {"College", 302}, |
| |
258 {"University", 303}, |
| |
259 {"Military", 304}, |
| |
260 {"Past Work Place", 305}, |
| |
261 {"Past Organization", 306}, |
| |
262 {"Other", 399}, |
| |
263 }; |
| |
264 |
| |
265 icq_ArrayType icq_MetaAffiliations[] = { |
| |
266 {"Alumni Org.", 200}, |
| |
267 {"Charity Org.", 201}, |
| |
268 {"Club/Social Org.", 202}, |
| |
269 {"Community Org.", 203}, |
| |
270 {"Cultural Org.", 204}, |
| |
271 {"Fan Clubs", 205}, |
| |
272 {"Fraternity/Sorority", 206}, |
| |
273 {"Hobbyists Org.", 207}, |
| |
274 {"International Org.", 208}, |
| |
275 {"Nature and Environment Org.", 209}, |
| |
276 {"Professional Org.", 210}, |
| |
277 {"Scientific/Technical Org.", 211}, |
| |
278 {"Self Improvement Group", 212}, |
| |
279 {"Spiritual/Religious Org.", 213}, |
| |
280 {"Sports Org.", 214}, |
| |
281 {"Support Org.", 215}, |
| |
282 {"Trade and Business Org.", 216}, |
| |
283 {"Union", 217}, |
| |
284 {"Voluntary Org.", 218}, |
| |
285 {"Other", 299}, |
| |
286 }; |
| |
287 |
| |
288 icq_ArrayType icq_MetaLanguages[] = { |
| |
289 {"Not Entered", 0}, |
| |
290 {"Arabic", 1}, |
| |
291 {"Bhojpuri", 2}, |
| |
292 {"Bulgarian", 3}, |
| |
293 {"Burmese", 4}, |
| |
294 {"Cantonese", 5}, |
| |
295 {"Catalan", 6}, |
| |
296 {"Chinese", 7}, |
| |
297 {"Croatian", 8}, |
| |
298 {"Czech", 9}, |
| |
299 {"Danish", 10}, |
| |
300 {"Dutch", 11}, |
| |
301 {"English", 12}, |
| |
302 {"Esperanto", 13}, |
| |
303 {"Estonian", 14}, |
| |
304 {"Farsi", 15}, |
| |
305 {"Finnish", 16}, |
| |
306 {"French", 17}, |
| |
307 {"Gaelic", 18}, |
| |
308 {"German", 19}, |
| |
309 {"Greek", 20}, |
| |
310 {"Hebrew", 21}, |
| |
311 {"Hindi", 22}, |
| |
312 {"Hungarian", 23}, |
| |
313 {"Icelandic", 24}, |
| |
314 {"Indonesian", 25}, |
| |
315 {"Italian", 26}, |
| |
316 {"Japanese", 27}, |
| |
317 {"Khmer", 28}, |
| |
318 {"Korean", 29}, |
| |
319 {"Lao", 30}, |
| |
320 {"Latvian", 31}, |
| |
321 {"Lithuanian", 32}, |
| |
322 {"Malay", 33}, |
| |
323 {"Norwegian", 34}, |
| |
324 {"Polish", 35}, |
| |
325 {"Portuguese", 36}, |
| |
326 {"Romanian", 37}, |
| |
327 {"Russian", 38}, |
| |
328 {"Serbian", 39}, |
| |
329 {"Slovak", 40}, |
| |
330 {"Slovenian", 41}, |
| |
331 {"Somali", 42}, |
| |
332 {"Spanish", 43}, |
| |
333 {"Swahili", 44}, |
| |
334 {"Swedish", 45}, |
| |
335 {"Tagalog", 46}, |
| |
336 {"Tatar", 47}, |
| |
337 {"Thai", 48}, |
| |
338 {"Turkish", 49}, |
| |
339 {"Ukrainian", 50}, |
| |
340 {"Urdu", 51}, |
| |
341 {"Vietnamese", 52}, |
| |
342 {"Yiddish", 53}, |
| |
343 {"Yoruba", 54}, |
| |
344 {"Afrikaans", 55}, |
| |
345 {"Bosnian", 56}, |
| |
346 {"Persian", 57}, |
| |
347 {"Albanian", 58}, |
| |
348 {"Armenian", 59}, |
| |
349 {"Punjabi", 60}, |
| |
350 {"Chamorro", 61}, |
| |
351 {"Mongolian", 62}, |
| |
352 {"Mandarin", 63}, |
| |
353 {"Taiwaness", 64}, |
| |
354 {"Macedonian", 65}, |
| |
355 {"Sindhi", 66}, |
| |
356 {"Welsh", 67}, |
| |
357 }; |
| |
358 |
| |
359 void hex_dump(char *data, long size) |
| |
360 { |
| |
361 long i; |
| |
362 long x; |
| |
363 int r=1; |
| |
364 char d[32]; |
| |
365 unsigned char bfr[64]; |
| |
366 for(i=0, x=0;;i++) |
| |
367 { |
| |
368 if(i<size) |
| |
369 { |
| |
370 if(x==0) |
| |
371 printf("%04lx: ", i); |
| |
372 #ifdef _WIN32 |
| |
373 sprintf(d, "%08x", data[i]); |
| |
374 #else |
| |
375 snprintf(d, 9, "%08x", data[i]); |
| |
376 #endif |
| |
377 printf("%c%c ", d[6], d[7]); |
| |
378 bfr[x]=data[i]; |
| |
379 if(bfr[x]<0x20) |
| |
380 bfr[x]='.'; |
| |
381 if(bfr[x]>0x7f) |
| |
382 bfr[x]='.'; |
| |
383 } |
| |
384 else |
| |
385 { |
| |
386 if(x==0) |
| |
387 break; |
| |
388 else |
| |
389 { |
| |
390 printf(" "); |
| |
391 bfr[x]=' '; |
| |
392 r=0; |
| |
393 } |
| |
394 } |
| |
395 x++; |
| |
396 if(!(x<16)) |
| |
397 { |
| |
398 bfr[x]=0; |
| |
399 printf("%s\n", bfr); |
| |
400 x=0; |
| |
401 if(!r) |
| |
402 break; |
| |
403 } |
| |
404 } |
| |
405 } |
| |
406 |
| |
407 /* simple mapping for udp status->tcp status translation function */ |
| |
408 struct icq_TCPStatusRec |
| |
409 { |
| |
410 unsigned long udp_status; |
| |
411 long tcp_status; |
| |
412 } icq_TCPStatusMap[] = { |
| |
413 { STATUS_OFFLINE , 0 }, |
| |
414 { STATUS_ONLINE , ICQ_TCP_STATUS_ONLINE }, |
| |
415 { STATUS_INVISIBLE , ICQ_TCP_STATUS_INVISIBLE }, |
| |
416 { STATUS_NA , ICQ_TCP_STATUS_NA }, |
| |
417 { STATUS_FREE_CHAT , ICQ_TCP_STATUS_FREE_CHAT }, |
| |
418 { STATUS_OCCUPIED , ICQ_TCP_STATUS_OCCUPIED }, |
| |
419 { STATUS_AWAY , ICQ_TCP_STATUS_AWAY }, |
| |
420 { STATUS_DND , ICQ_TCP_STATUS_DND }, |
| |
421 }; |
| |
422 |
| |
423 long icq_TCPXlateStatus(unsigned long udp_status) |
| |
424 { |
| |
425 unsigned int i; |
| |
426 for(i=0;i<sizeof(icq_TCPStatusMap)/sizeof(struct icq_TCPStatusRec);i++) |
| |
427 if(icq_TCPStatusMap[i].udp_status==udp_status) |
| |
428 return icq_TCPStatusMap[i].tcp_status; |
| |
429 /* warning: "couldn't find tcp status for %d, assuming 0", udp_status */ |
| |
430 return 0; |
| |
431 } |
| |
432 |
| |
433 void icq_FmtLog(ICQLINK *link, int level, const char *fmt, ...) |
| |
434 { |
| |
435 char buffer[2048]; |
| |
436 va_list ap; |
| |
437 va_start(ap, fmt); |
| |
438 |
| |
439 if(!link) |
| |
440 return; |
| |
441 #ifdef _MSVC_ |
| |
442 _vsnprintf(buffer, 1024, fmt, ap); |
| |
443 #else |
| |
444 (void)vsnprintf(buffer, 1024, fmt, ap); |
| |
445 #endif |
| |
446 va_end(ap); |
| |
447 |
| |
448 if(link->icq_Log && icq_LogLevel>=level) |
| |
449 (*link->icq_Log)(link, time(0L), level, buffer); |
| |
450 } |
| |
451 |
| |
452 /** |
| |
453 * Following functions used by qsort and bsearch to |
| |
454 * compare 2 pointers to icq_ArrayType object. |
| |
455 */ |
| |
456 int array_code_compare(const void *x, const void *y) |
| |
457 { |
| |
458 return ((icq_ArrayType*)x)->code - ((icq_ArrayType*)y)->code; |
| |
459 } |
| |
460 |
| |
461 const char *icq_GetCountryName(unsigned short code) |
| |
462 { |
| |
463 icq_ArrayType *res,key; |
| |
464 |
| |
465 key.code=code; |
| |
466 res=bsearch(&key, icq_Countries, sizeof(icq_Countries)/sizeof(icq_ArrayType), |
| |
467 sizeof(icq_ArrayType), array_code_compare); |
| |
468 |
| |
469 return res?res->name:"Unknown"; |
| |
470 } |
| |
471 |
| |
472 const char *icq_GetMetaOccupationName(unsigned short code) |
| |
473 { |
| |
474 icq_ArrayType *res,key; |
| |
475 |
| |
476 key.code=code; |
| |
477 res=bsearch(&key, icq_MetaOccupation, sizeof(icq_MetaOccupation)/sizeof(icq_ArrayType), |
| |
478 sizeof(icq_ArrayType), array_code_compare); |
| |
479 |
| |
480 return res?res->name:"Unknown"; |
| |
481 } |
| |
482 |
| |
483 const char *icq_GetMetaBackgroundName(unsigned short code) |
| |
484 { |
| |
485 icq_ArrayType *res,key; |
| |
486 |
| |
487 key.code=code; |
| |
488 res=bsearch(&key, icq_MetaPastBackgrounds, sizeof(icq_MetaPastBackgrounds)/sizeof(icq_ArrayType), |
| |
489 sizeof(icq_ArrayType), array_code_compare); |
| |
490 |
| |
491 return res?res->name:"Unknown"; |
| |
492 } |
| |
493 |
| |
494 const char *icq_GetMetaAffiliationName(unsigned short code) |
| |
495 { |
| |
496 icq_ArrayType *res,key; |
| |
497 |
| |
498 key.code=code; |
| |
499 res=bsearch(&key, icq_MetaAffiliations, sizeof(icq_MetaAffiliations)/sizeof(icq_ArrayType), |
| |
500 sizeof(icq_ArrayType), array_code_compare); |
| |
501 |
| |
502 return res?res->name:"Unknown"; |
| |
503 } |
| |
504 |
| |
505 const char *icq_GetMetaLanguageName(unsigned short code) |
| |
506 { |
| |
507 icq_ArrayType *res,key; |
| |
508 |
| |
509 key.code=code; |
| |
510 res=bsearch(&key, icq_MetaLanguages, sizeof(icq_MetaLanguages)/sizeof(icq_ArrayType), |
| |
511 sizeof(icq_ArrayType), array_code_compare); |
| |
512 |
| |
513 return res?res->name:"Unknown"; |
| |
514 } |
| |
515 |
| |
516 /******************************************** |
| |
517 returns a string describing the status or |
| |
518 a "Error" if no such string exists |
| |
519 *********************************************/ |
| |
520 const char *icq_ConvertStatus2Str(unsigned long status) |
| |
521 { |
| |
522 if((unsigned long)STATUS_OFFLINE == status) /* this because -1 & 0x01FF is not -1 */ |
| |
523 return "Offline"; |
| |
524 |
| |
525 if((status & STATUS_INVISIBLE) == STATUS_INVISIBLE) |
| |
526 return "Invisible"; |
| |
527 else if((status & STATUS_FREE_CHAT) == STATUS_FREE_CHAT) |
| |
528 return "Free for chat"; |
| |
529 else if((status & STATUS_DND) == STATUS_DND) |
| |
530 return "Do not disturb"; |
| |
531 else if((status & STATUS_OCCUPIED) == STATUS_OCCUPIED) |
| |
532 return "Occupied"; |
| |
533 else if((status & STATUS_NA) == STATUS_NA) |
| |
534 return "Not available"; |
| |
535 else if((status & STATUS_AWAY) == STATUS_AWAY) |
| |
536 return "Away"; |
| |
537 else if(!(status & 0x01FF)) |
| |
538 return "Online"; |
| |
539 else |
| |
540 return "Error"; |
| |
541 } |