1 /*
2 * Handles incoming and creates outgoing SNAC packets
3 * for the family 21 (old ICQ) commands.
4 *
5 * climm Copyright (C) © 2001-2010 Rüdiger Kuhlmann
6 *
7 * climm is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 dated June, 1991.
10 *
11 * climm is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 * License for more details.
15 *
16 * In addition, as a special exception permission is granted to link the
17 * code of this release of climm with the OpenSSL project's "OpenSSL"
18 * library, and distribute the linked executables. You must obey the GNU
19 * General Public License in all respects for all of the code used other
20 * than "OpenSSL". If you modify this file, you may extend this exception
21 * to your version of the file, but you are not obligated to do so. If you
22 * do not wish to do so, delete this exception statement from your version
23 * of this file.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this package; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 * 02111-1307, USA.
29 *
30 * $Id: oscar_oldicq.c 2864 2010-03-16 22:48:25Z kuhlmann $
31 */
32
33 #include "climm.h"
34 #include <assert.h>
35 #include "oscar_base.h"
36 #include "oscar_tlv.h"
37 #include "oscar_snac.h"
38 #include "oscar_oldicq.h"
39 #include "oscar_roster.h"
40 #include "packet.h"
41 #include "contact.h"
42 #include "connection.h"
43 #include "preferences.h"
44 #include "conv.h"
45 #include "im_response.h"
46 #include "im_request.h"
47 #include "util_ui.h"
48
49 static Packet *SnacMetaC (Server *serv, UWORD sub, UWORD type, UWORD ref);
50 static void SnacMetaSend (Server *serv, Packet *pak);
51
52 #define PacketWriteMetaLNTS(p,t,s) { PacketWrite2 (p, t); PacketWriteLen (p); PacketWriteLNTS (p, s); PacketWriteLenDone (p); }
53 #define PacketWriteMeta1(p,t,i) { PacketWrite2 (p, t); PacketWrite2 (p, 1); PacketWrite1 (p, i); }
54 #define PacketWriteMeta2(p,t,i) { PacketWrite2 (p, t); PacketWrite2 (p, 2); PacketWrite2 (p, i); }
55 #define PacketWriteMeta4(p,t,i) { PacketWrite2 (p, t); PacketWrite2 (p, 4); PacketWrite4 (p, i); }
56 #define PacketWriteMeta6(p,t,i,j,k) { PacketWrite2 (p, t); PacketWrite2 (p, 6); PacketWrite2 (p, i); PacketWrite2 (p, j); PacketWrite2 (p, k); }
57
58 #define META_TAG_UIN 310 /* LE32 */
59 #define META_TAG_FIRST 320
60 #define META_TAG_LAST 330
61 #define META_TAG_NICK 340
62 #define META_TAG_EMAIL 350 /* LNTS B */
63 #define META_TAG_AGERANGE 360 /* LE16 LE16 */
64 #define META_TAG_AGE 370 /* LE16 */
65 #define META_TAG_GENDER 380 /* B */
66 #define META_TAG_LANG 390 /* LE16 */
67 #define META_TAG_HOME_CITY 400
68 #define META_TAG_HOME_STATE 410
69 #define META_TAG_HOME_CTRY 420 /* LE16 */
70 #define META_TAG_WRK_COMP 430
71 #define META_TAG_WRK_DEPT 440
72 #define META_TAG_WRK_POS 450
73 #define META_TAG_WRK_OCC 460 /* LE16 */
74 #define META_TAG_AFFIL 470 /* LE16 LNTS */
75
76 #define META_TAG_INTER 490 /* LE16 LNTS */
77
78 #define META_TAG_PASTINFO 510 /* LE16 LNTS */
79
80 #define META_TAG_HP_CAT 530 /* LE16 LNTS */
81 #define META_TAG_HP_URL 531 /* LE16 LNTS */
82
83 #define META_TAG_SRCH_STRING 550
84 #define META_TAG_SRCH_ONLINE 560 /* B */
85 #define META_TAG_BIRTHDAY 570 /* LE16 LE16 LE16 */
86
87 #define META_TAG_ABOUT 600
88 #define META_TAG_HOME_STREET 610
89 #define META_TAG_HOME_ZIP 620 /* LE32 */
90 #define META_TAG_HOME_PHONE 630
91 #define META_TAG_HOME_FAX 640
92 #define META_TAG_HOME_CELL 650
93 #define META_TAG_WRK_STREET 660
94 #define META_TAG_WRK_CITY 670
95 #define META_TAG_WRK_STATE 680
96 #define META_TAG_WRK_CTRY 690 /* LE16 */
97 #define META_TAG_WRK_ZIP 700 /* LE32 */
98 #define META_TAG_WRK_PHONE 710
99 #define META_TAG_WRK_FAX 720
100 #define META_TAG_WRK_URL 730
101
102 #define META_TAG_AUTHREQ 760 /* B (yes, 760, NOT 780) */
103 #define META_TAG_WEBAWARE 780 /* B */
104
105 #define META_TAG_TZ 790 /* SB */
106 #define META_TAG_ORIG_CITY 800
107 #define META_TAG_ORIG_STATE 810
108 #define META_TAG_ORIG_CTRY 820 /* LE16 */
109
110 /*
111 * Create meta request package.
112 */
SnacMetaC(Server * serv,UWORD sub,UWORD type,UWORD ref)113 static Packet *SnacMetaC (Server *serv, UWORD sub, UWORD type, UWORD ref)
114 {
115 Packet *pak;
116
117 serv->oscar_icq_seq = serv->oscar_icq_seq ? (serv->oscar_icq_seq + 1) % 0x7fff : 2;
118
119 pak = SnacC (serv, 21, 2, 0, (ref ? ref : rand () % 0x7fff) + (serv->oscar_icq_seq << 16));
120 PacketWriteTLV (pak, 1);
121 PacketWriteLen (pak);
122 PacketWrite4 (pak, serv->oscar_uin);
123 PacketWrite2 (pak, sub);
124 PacketWrite2 (pak, serv->oscar_icq_seq);
125 if (type)
126 PacketWrite2 (pak, type);
127
128 return pak;
129 }
130
131 /*
132 * Complete & send meta request package.
133 */
SnacMetaSend(Server * serv,Packet * pak)134 static void SnacMetaSend (Server *serv, Packet *pak)
135 {
136 PacketWriteLenDone (pak);
137 PacketWriteTLVDone (pak);
138 SnacSend (serv, pak);
139 }
140
141 /*
142 * SRV_TOICQERR - SNAC(15,1)
143 */
JUMP_SNAC_F(SnacSrvToicqerr)144 JUMP_SNAC_F(SnacSrvToicqerr)
145 {
146 Server *serv = event->conn->serv;
147 Packet *pak = event->pak;
148 if ((pak->ref & 0xffff) == 0x4231)
149 {
150 rl_print (i18n (2206, "The server doesn't want to give us offline messages.\n"));
151 }
152 else
153 {
154 UWORD err = PacketReadB2 (pak);
155 Event *oevent;
156
157 if ((oevent = QueueDequeue (serv->conn, QUEUE_REQUEST_META, pak->ref)))
158 {
159 rl_printf (i18n (2207, "Protocol error in command to old ICQ server: %d.\n"), err);
160 if (err == 2)
161 rl_printf (i18n (2515, "You queried already too many users today - come back tomorrow.\n"));
162 else if (err == 5)
163 rl_printf (i18n (2516, "The query got stuck. Or somesuch. Try again later.\n"));
164 else
165 rl_printf (i18n (2517, "I'm out of wisdom about the server's problem. It just didn't work out.\n"));
166 EventD (oevent);
167 }
168 else if ((pak->ref & 0xffff) != 0x4242)
169 {
170 rl_printf (i18n (2207, "Protocol error in command to old ICQ server: %d.\n"), err);
171 rl_print (s_dump (pak->data + pak->rpos, pak->len - pak->rpos));
172 }
173 }
174 }
175
176 /*
177 * CLI_REQOFFLINEMSGS - SNAC(15,2) - 60
178 */
SnacCliReqofflinemsgs(Server * serv)179 void SnacCliReqofflinemsgs (Server *serv)
180 {
181 Packet *pak;
182
183 pak = SnacMetaC (serv, 60, 0, 0x4231);
184 SnacMetaSend (serv, pak);
185 }
186
187 /*
188 * CLI_ACKOFFLINEMSGS - SNAC(15,2) - 62
189 */
SnacCliAckofflinemsgs(Server * serv)190 void SnacCliAckofflinemsgs (Server *serv)
191 {
192 Packet *pak;
193
194 pak = SnacMetaC (serv, 62, 0, 0);
195 SnacMetaSend (serv, pak);
196 }
197
198 /*
199 * CLI_METASETGENERAL - SNAC(15,2) - 2000/1002
200 */
SnacCliMetasetgeneral(Server * serv,Contact * cont)201 void SnacCliMetasetgeneral (Server *serv, Contact *cont)
202 {
203 Packet *pak;
204
205 #if 0
206 pak = SnacMetaC (serv, 2000, META_SET_GENERAL_INFO, 0);
207 if (cont->meta_general)
208 {
209 PacketWriteLNTS (pak, c_out (cont->meta_general->nick));
210 PacketWriteLNTS (pak, c_out (cont->meta_general->first));
211 PacketWriteLNTS (pak, c_out (cont->meta_general->last));
212 PacketWriteLNTS (pak, c_out (cont->meta_general->email));
213 PacketWriteLNTS (pak, c_out (cont->meta_general->city));
214 PacketWriteLNTS (pak, c_out (cont->meta_general->state));
215 PacketWriteLNTS (pak, c_out (cont->meta_general->phone));
216 PacketWriteLNTS (pak, c_out (cont->meta_general->fax));
217 PacketWriteLNTS (pak, c_out (cont->meta_general->street));
218 PacketWriteLNTS (pak, c_out (cont->meta_general->cellular));
219 PacketWriteLNTS (pak, c_out (cont->meta_general->zip));
220 PacketWrite2 (pak, cont->meta_general->country);
221 PacketWrite1 (pak, cont->meta_general->tz);
222 PacketWrite1 (pak, cont->meta_general->webaware);
223 }
224 else
225 {
226 PacketWriteLNTS (pak, c_out (cont->nick));
227 PacketWriteLNTS (pak, "<unset>");
228 PacketWriteLNTS (pak, "<unset>");
229 PacketWriteLNTS (pak, "");
230 PacketWriteLNTS (pak, "");
231 PacketWriteLNTS (pak, "");
232 PacketWriteLNTS (pak, "");
233 PacketWriteLNTS (pak, "");
234 PacketWriteLNTS (pak, "");
235 PacketWriteLNTS (pak, "");
236 PacketWriteLNTS (pak, "");
237 PacketWrite2 (pak, 0);
238 PacketWrite1 (pak, 0);
239 PacketWrite1 (pak, 0);
240 }
241 #else
242 pak = SnacMetaC (serv, 2000, META_SAVE_INFO, 0);
243 if (cont->meta_general)
244 {
245 ContactMeta *ml;
246
247 PacketWriteMetaLNTS (pak, META_TAG_NICK, c_out (cont->meta_general->nick));
248 PacketWriteMetaLNTS (pak, META_TAG_FIRST, c_out (cont->meta_general->first));
249 PacketWriteMetaLNTS (pak, META_TAG_LAST, c_out (cont->meta_general->last));
250
251 PacketWrite2 (pak, META_TAG_EMAIL);
252 PacketWriteLen (pak);
253 PacketWriteLNTS (pak, c_out (cont->meta_general->email));
254 PacketWrite1 (pak, 0);
255 PacketWriteLenDone (pak);
256
257 for (ml = cont->meta_email ; ml; ml = ml->next)
258 {
259 if (!ml->text || !*ml->text)
260 continue;
261 PacketWrite2 (pak, META_TAG_EMAIL);
262 PacketWriteLen (pak);
263 PacketWriteLNTS (pak, c_out (ml->text));
264 PacketWrite1 (pak, ml->data);
265 PacketWriteLenDone (pak);
266 }
267
268 PacketWriteMetaLNTS (pak, META_TAG_HOME_CITY, c_out (cont->meta_general->city));
269 PacketWriteMetaLNTS (pak, META_TAG_HOME_STATE, c_out (cont->meta_general->state));
270 PacketWriteMetaLNTS (pak, META_TAG_HOME_PHONE, c_out (cont->meta_general->phone));
271 PacketWriteMetaLNTS (pak, META_TAG_HOME_FAX, c_out (cont->meta_general->fax));
272 PacketWriteMetaLNTS (pak, META_TAG_HOME_STREET, c_out (cont->meta_general->street));
273 PacketWriteMetaLNTS (pak, META_TAG_HOME_CELL, c_out (cont->meta_general->cellular));
274 PacketWriteMeta4 (pak, META_TAG_HOME_ZIP, atoi (cont->meta_general->zip));
275
276 PacketWriteMeta2 (pak, META_TAG_HOME_CTRY, cont->meta_general->country);
277 PacketWriteMeta2 (pak, 835, 0);
278 PacketWriteMeta4 (pak, 621, 0);
279 PacketWriteMeta1 (pak, META_TAG_TZ, -cont->meta_general->tz/2);
280
281 PacketWriteMeta1 (pak, META_TAG_WEBAWARE, cont->meta_general->webaware);
282 PacketWriteMeta1 (pak, META_TAG_AUTHREQ, !cont->meta_general->auth);
283 }
284 else
285 {
286 PacketWriteMetaLNTS (pak, META_TAG_NICK, c_out (cont->nick));
287 PacketWriteMetaLNTS (pak, META_TAG_FIRST, "<unset>");
288 PacketWriteMetaLNTS (pak, META_TAG_LAST, "<unset>");
289
290 PacketWrite2 (pak, META_TAG_EMAIL);
291 PacketWriteLen (pak);
292 PacketWriteLNTS (pak, "");
293 PacketWrite1 (pak, 1);
294 PacketWriteLenDone (pak);
295
296 PacketWriteMetaLNTS (pak, META_TAG_HOME_CITY, "");
297 PacketWriteMetaLNTS (pak, META_TAG_HOME_STATE, "");
298 PacketWriteMetaLNTS (pak, META_TAG_HOME_PHONE, "");
299 PacketWriteMetaLNTS (pak, META_TAG_HOME_FAX, "");
300 PacketWriteMetaLNTS (pak, META_TAG_HOME_STREET, "");
301 PacketWriteMetaLNTS (pak, META_TAG_HOME_CELL, "");
302 PacketWriteMetaLNTS (pak, META_TAG_HOME_ZIP, "");
303 PacketWriteMeta2 (pak, META_TAG_HOME_CTRY, 0);
304 PacketWriteMeta1 (pak, META_TAG_TZ, 0);
305 PacketWriteMeta1 (pak, META_TAG_WEBAWARE, 0);
306 PacketWriteMeta1 (pak, META_TAG_AUTHREQ, 0);
307 }
308
309 #if 0
310 PacketWriteMeta1 (pak, 760, 0);
311 PacketWriteMeta1 (pak, 780, 0);
312 PacketWriteMeta4 (pak, 620, 0);
313 PacketWriteMeta2 (pak, 420, 0);
314 PacketWriteMeta1 (pak, 790, -2);
315 PacketWriteMeta2 (pak, 820, 0);
316 PacketWriteMeta2 (pak, 370, 99);
317 PacketWriteMeta2 (pak, 380, 2);
318 PacketWriteMeta2 (pak, 531, 0);
319
320 PacketWrite2 (pak, 570);
321 PacketWrite2 (pak, 6);
322 PacketWrite2 (pak, 0);
323 PacketWrite2 (pak, 0);
324 PacketWrite2 (pak, 0);
325
326 PacketWrite2 (pak, 350);
327 PacketWriteLen (pak);
328 PacketWriteLNTS (pak, "email@adresse");
329 PacketWrite1 (pak, 1);
330 PacketWriteLenDone (pak);
331
332 PacketWriteMeta4 (pak, 690, 0);
333 PacketWriteMeta2 (pak, 460, 0);
334 PacketWriteMeta4 (pak, 490, 0);
335 PacketWriteMeta4 (pak, 490, 0);
336 PacketWriteMeta4 (pak, 490, 0);
337 PacketWriteMeta4 (pak, 470, 0);
338 PacketWriteMeta4 (pak, 470, 0);
339 PacketWriteMeta4 (pak, 470, 0);
340 PacketWriteMeta4 (pak, 510, 0);
341 PacketWriteMeta4 (pak, 510, 0);
342 PacketWriteMeta4 (pak, 510, 0);
343 #endif
344
345 #endif
346 SnacMetaSend (serv, pak);
347 SnacCliSetlastupdate (serv);
348 }
349
350 /*
351 * CLI_METASETABOUT - SNAC(15,2) - 2000/1030
352 */
353
SnacCliMetasetabout(Server * serv,const char * text)354 void SnacCliMetasetabout (Server *serv, const char *text)
355 {
356 Packet *pak;
357 #if 0
358 pak = SnacMetaC (serv, 2000, META_SET_ABOUT_INFO, 0);
359 PacketWriteLNTS (pak, c_out (text));
360 #else
361 pak = SnacMetaC (serv, 2000, META_SAVE_INFO, 0);
362 PacketWriteMetaLNTS (pak, META_TAG_ABOUT, c_out (text));
363 #endif
364 SnacMetaSend (serv, pak);
365 SnacCliSetlastupdate (serv);
366 }
367
368 /*
369 * CLI_METASETMORE - SNAC(15,2) - 2000/1021
370 */
SnacCliMetasetmore(Server * serv,Contact * cont)371 void SnacCliMetasetmore (Server *serv, Contact *cont)
372 {
373 Packet *pak;
374
375 #if 0
376 pak = SnacMetaC (serv, 2000, META_SET_MORE_INFO, 0);
377 if (cont->meta_more)
378 {
379 PacketWrite2 (pak, cont->meta_more->age);
380 PacketWrite1 (pak, cont->meta_more->sex);
381 PacketWriteLNTS (pak, c_out (cont->meta_more->homepage));
382 PacketWrite2 (pak, cont->meta_more->year);
383 PacketWrite1 (pak, cont->meta_more->month);
384 PacketWrite1 (pak, cont->meta_more->day);
385 PacketWrite1 (pak, cont->meta_more->lang1);
386 PacketWrite1 (pak, cont->meta_more->lang2);
387 PacketWrite1 (pak, cont->meta_more->lang3);
388 }
389 else
390 {
391 PacketWrite2 (pak, 0);
392 PacketWrite1 (pak, 0);
393 PacketWriteLNTS (pak, "");
394 PacketWrite2 (pak, 0);
395 PacketWrite1 (pak, 0);
396 PacketWrite1 (pak, 0);
397 PacketWrite1 (pak, 0);
398 PacketWrite1 (pak, 0);
399 PacketWrite1 (pak, 0);
400 }
401 #else
402 pak = SnacMetaC (serv, 2000, META_SAVE_INFO, 0);
403 if (cont->meta_more)
404 {
405 PacketWriteMeta2 (pak, META_TAG_AGE, cont->meta_more->age);
406 PacketWriteMeta1 (pak, META_TAG_GENDER, cont->meta_more->sex);
407 PacketWriteMetaLNTS (pak, META_TAG_HP_URL, c_out (cont->meta_more->homepage));
408 PacketWriteMeta6 (pak, META_TAG_BIRTHDAY, cont->meta_more->year, cont->meta_more->month, cont->meta_more->day);
409 PacketWriteMeta1 (pak, META_TAG_LANG, cont->meta_more->lang1);
410 PacketWriteMeta1 (pak, META_TAG_LANG, cont->meta_more->lang2);
411 PacketWriteMeta1 (pak, META_TAG_LANG, cont->meta_more->lang3);
412 }
413 else
414 {
415 PacketWriteMeta2 (pak, META_TAG_AGE, 0);
416 PacketWriteMeta1 (pak, META_TAG_GENDER, 0);
417 PacketWriteMetaLNTS (pak, META_TAG_HP_URL, "");
418 PacketWriteMeta6 (pak, META_TAG_BIRTHDAY, 0, 0, 0);
419 PacketWriteMeta1 (pak, META_TAG_LANG, 0);
420 PacketWriteMeta1 (pak, META_TAG_LANG, 0);
421 PacketWriteMeta1 (pak, META_TAG_LANG, 0);
422 }
423
424
425 #endif
426 SnacMetaSend (serv, pak);
427 SnacCliSetlastupdate (serv);
428 }
429
430 /*
431 * CLI_METASETPASS - SNAC(15,2) - 2000/1070
432 */
SnacCliMetasetpass(Server * serv,const char * newpass)433 void SnacCliMetasetpass (Server *serv, const char *newpass)
434 {
435 Packet *pak;
436
437 pak = SnacMetaC (serv, 2000, 1070, 0);
438 PacketWriteLNTS (pak, c_out (newpass));
439 SnacMetaSend (serv, pak);
440 }
441
442 /*
443 * CLI_METAREQINFO - SNAC(15,2) - 2000/1202
444 */
SnacCliMetareqmoreinfo(Server * serv,Contact * cont)445 UDWORD SnacCliMetareqmoreinfo (Server *serv, Contact *cont)
446 {
447 Packet *pak;
448 UDWORD ref;
449
450 pak = SnacMetaC (serv, 2000, 1202, 0);
451 ref = pak->ref;
452 PacketWrite4 (pak, cont->uin);
453 SnacMetaSend (serv, pak);
454 return ref;
455 }
456
457 /*
458 * CLI_METAREQINFO - SNAC(15,2) - 2000/1232
459 */
SnacCliMetareqinfo(Server * serv,Contact * cont)460 UDWORD SnacCliMetareqinfo (Server *serv, Contact *cont)
461 {
462 Packet *pak;
463 UDWORD ref;
464
465 pak = SnacMetaC (serv, 2000, META_REQ_INFO, 0);
466 ref = pak->ref;
467 PacketWrite4 (pak, cont->uin);
468 SnacMetaSend (serv, pak);
469 return ref;
470 }
471
472 /*
473 * CLI_SEARCHBYPERSINF - SNAC(15,2) - 2000/1375
474 */
SnacCliSearchbypersinf(Server * serv,const char * email,const char * nick,const char * name,const char * surname)475 void SnacCliSearchbypersinf (Server *serv, const char *email, const char *nick, const char *name, const char *surname)
476 {
477 Packet *pak;
478
479 pak = SnacMetaC (serv, 2000, META_SEARCH_PERSINFO, 0);
480 PacketWrite2 (pak, 320); /* key: first name */
481 PacketWriteLLNTS (pak, c_out (name));
482 PacketWrite2 (pak, 330); /* key: last name */
483 PacketWriteLLNTS (pak, c_out (surname));
484 PacketWrite2 (pak, 340); /* key: nick */
485 PacketWriteLLNTS (pak, c_out (nick));
486 PacketWrite2 (pak, 350); /* key: email address */
487 PacketWriteLLNTS (pak, c_out (email));
488 SnacMetaSend (serv, pak);
489 }
490
491 /*
492 * CLI_SEARCHBYMAIL - SNAC(15,2) - 2000/{1395,1321}
493 */
SnacCliSearchbymail(Server * serv,const char * email)494 void SnacCliSearchbymail (Server *serv, const char *email)
495 {
496 Packet *pak;
497
498 pak = SnacMetaC (serv, 2000, META_SEARCH_EMAIL, 0);
499 PacketWrite2 (pak, 350); /* key: email address */
500 PacketWriteLLNTS (pak, c_out (email));
501 SnacMetaSend (serv, pak);
502 }
503
504 /*
505 * CLI_SEARCHRANDOM - SNAC(15,2) - 2000/1870
506 */
SnacCliSearchrandom(Server * serv,UWORD group)507 UDWORD SnacCliSearchrandom (Server *serv, UWORD group)
508 {
509 Packet *pak;
510 UDWORD ref;
511
512 pak = SnacMetaC (serv, 2000, META_SEARCH_RANDOM, 0);
513 ref = pak->ref;
514 PacketWrite2 (pak, group);
515 SnacMetaSend (serv, pak);
516 return ref;
517 }
518
519 /*
520 * CLI_SETRANDOM - SNAC(15,2) - 2000/1880
521 */
SnacCliSetrandom(Server * serv,UWORD group)522 void SnacCliSetrandom (Server *serv, UWORD group)
523 {
524 Packet *pak;
525
526 pak = SnacMetaC (serv, 2000, META_SET_RANDOM, serv->conn->connect & CONNECT_OK ? 0 : 0x4242);
527 PacketWrite2 (pak, group);
528 if (group)
529 {
530 PacketWriteB4 (pak, 0x00000220);
531 PacketWriteB4 (pak, 0);
532 PacketWriteB4 (pak, 0);
533 PacketWriteB4 (pak, 0);
534 PacketWrite1 (pak, serv->oscar_dc && serv->oscar_dc->connect & CONNECT_OK
535 ? ServerPrefVal (serv, CO_OSCAR_DC_MODE) & 15 : 0);
536 PacketWrite2 (pak, serv->oscar_dc && serv->oscar_dc->connect & CONNECT_OK
537 ? serv->oscar_dc->version : 0);
538 PacketWriteB4 (pak, 0);
539 PacketWriteB4 (pak, 0x00005000);
540 PacketWriteB4 (pak, 0x00000300);
541 PacketWrite2 (pak, 0);
542 }
543 SnacMetaSend (serv, pak);
544 }
545
546 /*
547 * CLI_SEARCHWP - SNAC(15,2) - 2000/1331
548 */
SnacCliSearchwp(Server * serv,const MetaWP * wp)549 void SnacCliSearchwp (Server *serv, const MetaWP *wp)
550 {
551 Packet *pak;
552
553 pak = SnacMetaC (serv, 2000, META_SEARCH_WP, 0);
554 PacketWriteLNTS (pak, c_out (wp->first));
555 PacketWriteLNTS (pak, c_out (wp->last));
556 PacketWriteLNTS (pak, c_out (wp->nick));
557 PacketWriteLNTS (pak, c_out (wp->email));
558 PacketWrite2 (pak, wp->minage);
559 PacketWrite2 (pak, wp->maxage);
560 PacketWrite1 (pak, wp->sex);
561 PacketWrite1 (pak, wp->language);
562 PacketWriteLNTS (pak, c_out (wp->city));
563 PacketWriteLNTS (pak, c_out (wp->state));
564 PacketWriteB2 (pak, wp->country);
565 PacketWriteLNTS (pak, c_out (wp->company));
566 PacketWriteLNTS (pak, c_out (wp->department));
567 PacketWriteLNTS (pak, c_out (wp->position));
568 PacketWrite1 (pak, 0); /* occupation); */
569 PacketWriteB2 (pak, 0); /* past information); */
570 PacketWriteLNTS (pak, NULL); /* description); */
571 PacketWriteB2 (pak, 0); /* interests-category); */
572 PacketWriteLNTS (pak, NULL); /* interests-specification); */
573 PacketWriteB2 (pak, 0); /* affiliation/organization); */
574 PacketWriteLNTS (pak, NULL); /* description); */
575 PacketWriteB2 (pak, 0); /* homepage category); */
576 PacketWriteLNTS (pak, NULL); /* description); */
577 PacketWrite1 (pak, wp->online);
578 SnacMetaSend (serv, pak);
579 }
580
581 /*
582 * CLI_SENDSMS - SNAC(15,2) - 2000/5250
583 */
SnacCliSendsms(Server * serv,const char * target,const char * text)584 void SnacCliSendsms (Server *serv, const char *target, const char *text)
585 {
586 Packet *pak;
587 char buf[2000];
588 time_t t = time (NULL);
589
590 snprintf (buf, sizeof (buf), "<icq_sms_message><destination>%s</destination>"
591 "<text>%s (%s www.climm.org)</text><codepage>utf8</codepage><senders_UIN>%s</senders_UIN>"
592 "<senders_name>%s</senders_name><delivery_receipt>Yes</delivery_receipt>"
593 "<time>%s</time></icq_sms_message>",
594 target, text, serv->screen, serv->screen, "climm",
595 s_strftime (&t, "%a, %d %b %Y %H:%M:%S GMT", 1));
596
597 pak = SnacMetaC (serv, 2000, META_SEND_SMS, 0);
598 PacketWriteB2 (pak, 1);
599 PacketWriteB2 (pak, 22);
600 PacketWriteB4 (pak, 0);
601 PacketWriteB4 (pak, 0);
602 PacketWriteB4 (pak, 0);
603 PacketWriteB4 (pak, 0);
604 PacketWriteTLVStr (pak, 0, buf);
605 SnacMetaSend (serv, pak);
606 }
607
608 /*
609 * SRV_FROMOLDICQ - SNAC(15,3)
610 */
JUMP_SNAC_F(SnacSrvFromicqsrv)611 JUMP_SNAC_F(SnacSrvFromicqsrv)
612 {
613 Server *serv = event->conn->serv;
614 TLV *tlv;
615 Packet *p, *pak;
616 UDWORD len, uin, type /*, id*/;
617
618 pak = event->pak;
619 tlv = TLVRead (pak, PacketReadLeft (pak), -1);
620 if (tlv[1].str.len < 10)
621 {
622 SnacSrvUnknown (event);
623 TLVD (tlv);
624 return;
625 }
626 p = PacketCreate (&tlv[1].str);
627 p->ref = pak->ref; /* copy reference */
628 len = PacketRead2 (p);
629 uin = PacketRead4 (p);
630 type= PacketRead2 (p);
631 /* id=*/ PacketRead2 (p);
632 if (uin != serv->oscar_uin)
633 {
634 if (prG->verbose & DEB_PROTOCOL)
635 {
636 rl_printf (i18n (1919, "UIN mismatch: %ld vs %ld.\n"), UD2UL (serv->oscar_uin), UD2UL (uin));
637 SnacSrvUnknown (event);
638 }
639 TLVD (tlv);
640 PacketD (p);
641 return;
642 }
643 else if (len != tlv[1].str.len - 2)
644 {
645 if (prG->verbose & DEB_PROTOCOL)
646 {
647 rl_print (i18n (1743, "Size mismatch in packet lengths.\n"));
648 SnacSrvUnknown (event);
649 }
650 TLVD (tlv);
651 PacketD (p);
652 return;
653 }
654
655 TLVD (tlv);
656 switch (type)
657 {
658 case 65:
659 if (len >= 14)
660 Recv_Message (serv, p);
661 break;
662
663 case 66:
664 SnacCliAckofflinemsgs (serv);
665 break;
666
667 case 2010:
668 Meta_User (serv, ContactUIN (serv, uin), p);
669 break;
670
671 default:
672 SnacSrvUnknown (event);
673 break;
674 }
675 PacketD (p);
676 }
677
678 #define META_SRV_GEN_UPDATE 100
679 #define META_SRV_OTHER_UPDATE 120
680 #define META_SRV_ABOUT_UPDATE 130
681 #define META_SRV_SMS_OK 150
682 #define META_SRV_PASS_UPDATE 170
683 #define META_SRV_GEN 200
684 #define META_SRV_WORK 210
685 #define META_SRV_MORE 220
686 #define META_SRV_ABOUT 230
687 #define META_SRV_INTEREST 240
688 #define META_SRV_BACKGROUND 250
689 #define META_SRV_MOREEMAIL 235
690 #define META_SRV_INFO 260
691 #define META_SRV_UNKNOWN_270 270
692 #define META_SRV_WP_FOUND 420
693 #define META_SRV_WP_LAST_USER 430
694 #define META_SRV_RANDOM 870
695 #define META_SRV_RANDOM_UPDATE 880
696 #define META_SRV_METATLV_UPDATE 3135
697
Auto_Reply(Server * serv,Contact * cont)698 void Auto_Reply (Server *serv, Contact *cont)
699 {
700 const char *temp = NULL;
701
702 if (!(prG->flags & FLAG_AUTOREPLY) || !cont)
703 return;
704
705 switch (ContactClearInv (cont->status))
706 {
707 case imr_dnd: temp = ContactPrefStr (cont, CO_TAUTODND); break;
708 case imr_occ: temp = ContactPrefStr (cont, CO_TAUTOOCC); break;
709 case imr_na: temp = ContactPrefStr (cont, CO_TAUTONA); break;
710 case imr_away: temp = ContactPrefStr (cont, CO_TAUTOAWAY); break;
711 case imr_ffc: temp = ContactPrefStr (cont, CO_TAUTOFFC); break;
712 case imr_offline: return;
713 case imr_online:
714 if (ContactIsInv (cont->status))
715 temp = ContactPrefStr (cont, CO_TAUTOINV);
716 else
717 return;
718 }
719
720 if (!temp || !*temp)
721 {
722 switch (ContactClearInv (cont->status))
723 {
724 case imr_dnd: temp = ContactPrefStr (cont, CO_AUTODND); break;
725 case imr_occ: temp = ContactPrefStr (cont, CO_AUTOOCC); break;
726 case imr_na: temp = ContactPrefStr (cont, CO_AUTONA); break;
727 case imr_away: temp = ContactPrefStr (cont, CO_AUTOAWAY); break;
728 case imr_ffc: temp = ContactPrefStr (cont, CO_AUTOFFC); break;
729 case imr_offline: assert (0);
730 case imr_online:
731 assert (ContactIsInv (cont->status));
732 temp = ContactPrefStr (cont, CO_AUTOINV);
733 }
734 }
735
736 IMCliMsg (cont, MSG_AUTO, temp, NULL);
737 }
738
739 #define s_read(s) s_repl (&s, ConvFromCont (PacketReadL2Str (pak, NULL), cont))
740
Meta_Read_List(Packet * pak,ContactMeta ** list,Contact * cont)741 static BOOL Meta_Read_List (Packet *pak, ContactMeta **list, Contact *cont)
742 {
743 UBYTE i, j;
744 UWORD data;
745 const char *text;
746
747 i = PacketRead1 (pak);
748 ContactMetaD (*list);
749 *list = NULL;
750 for (j = 0; j < i; j++)
751 {
752 data = PacketRead2 (pak);
753 text = ConvFromCont (PacketReadL2Str (pak, NULL), cont);
754 if (data && text && *text)
755 ContactMetaAdd (list, data, text);
756 }
757 return TRUE;
758 }
759
Meta_User(Server * serv,Contact * cont,Packet * pak)760 void Meta_User (Server *serv, Contact *cont, Packet *pak)
761 {
762 UWORD subtype;
763 UDWORD result;
764 Event *event = NULL;
765
766 if (!cont)
767 return;
768 subtype = PacketRead2 (pak);
769 result = PacketRead1 (pak);
770
771 switch (subtype)
772 {
773 case META_SRV_PASS_UPDATE:
774 rl_printf (i18n (2136, "Password change was %s%s%s.\n"),
775 COLCLIENT, result == META_SUCCESS ? i18n (1393, "successful")
776 : i18n (1394, "unsuccessful"), COLNONE);
777 break;
778 case META_SRV_ABOUT_UPDATE:
779 rl_printf (i18n (2137, "About info change was %s%s%s.\n"),
780 COLCLIENT, result == META_SUCCESS ? i18n (1393, "successful")
781 : i18n (1394, "unsuccessful"), COLNONE);
782 break;
783 case META_SRV_GEN_UPDATE:
784 rl_printf (i18n (2138, "Info change was %s%s%s.\n"),
785 COLCLIENT, result == META_SUCCESS ? i18n (1393, "successful")
786 : i18n (1394, "unsuccessful"), COLNONE);
787 break;
788 case META_SRV_OTHER_UPDATE:
789 rl_printf (i18n (2139, "Other info change was %s%s%s.\n"),
790 COLCLIENT, result == META_SUCCESS ? i18n (1393, "successful")
791 : i18n (1394, "unsuccessful"), COLNONE);
792 break;
793 case META_SRV_RANDOM_UPDATE:
794 if ((pak->ref & 0xffff) != 0x4242)
795 rl_printf (i18n (2140, "Random chat group change was %s%s%s.\n"),
796 COLCLIENT, result == META_SUCCESS ? i18n (1393, "successful")
797 : i18n (1394, "unsuccessful"), COLNONE);
798 break;
799 case META_SRV_METATLV_UPDATE:
800 rl_printf (i18n (2690, "Meta info change was %s%s%s.\n"),
801 COLCLIENT, result == META_SUCCESS ? i18n (1393, "successful")
802 : i18n (1394, "unsuccessful"), COLNONE);
803 break;
804 }
805
806 switch (result) /* default error handling */
807 {
808 case 0x32:
809 case 0x14:
810 if ((event = QueueDequeue (serv->conn, QUEUE_REQUEST_META, pak->ref)))
811 EventD (event);
812 rl_printf ("%s ", s_now);
813 rl_printf (i18n (2141, "Search %sfailed%s.\n"), COLCLIENT, COLNONE);
814 return;
815 case META_READONLY:
816 rl_printf ("%s %s\n", s_now, i18n (1900, "It's readonly."));
817 return;
818 case META_SUCCESS:
819 break;
820 case 0x46:
821 rl_printf ("%s\n", pak->data + pak->rpos);
822 return;
823 default:
824 rl_printf (i18n (1940, "Unknown Meta User result %lx.\n"), UD2UL (result));
825 return;
826 }
827
828 switch (subtype)
829 {
830 case META_SRV_ABOUT_UPDATE:
831 case META_SRV_OTHER_UPDATE:
832 case META_SRV_GEN_UPDATE:
833 case META_SRV_PASS_UPDATE:
834 case META_SRV_RANDOM_UPDATE:
835 case META_SRV_METATLV_UPDATE:
836 return;
837 case META_SRV_INFO:
838 case META_SRV_GEN:
839 case META_SRV_MORE:
840 case META_SRV_MOREEMAIL:
841 case META_SRV_WORK:
842 case META_SRV_ABOUT:
843 case META_SRV_INTEREST:
844 case META_SRV_BACKGROUND:
845 case META_SRV_UNKNOWN_270:
846 case META_SRV_RANDOM:
847 if (!(event = QueueDequeue (serv->conn, QUEUE_REQUEST_META, pak->ref)) || !event->callback)
848 {
849 if (prG->verbose)
850 rl_printf ("FIXME: meta reply ref %lx not found.\n", UD2UL (pak->ref));
851 return;
852 }
853
854 if (event->cont)
855 cont = event->cont;
856 }
857
858 switch (subtype)
859 {
860 strc_t data;
861 UWORD wdata, i, j;
862 UDWORD dwdata, uin;
863 MetaGeneral *mg;
864 MetaMore *mm;
865 MetaWork *mw;
866 MetaObsolete *mo;
867
868 case META_SRV_SMS_OK:
869 PacketRead4 (pak);
870 PacketRead2 (pak);
871 PacketReadB2Str (pak, NULL);
872 data = PacketReadB2Str (pak, NULL);
873 rl_printf (i18n (2080, "Server SMS delivery response:\n%s\n"), ConvFromServ (data));
874 break;
875 case META_SRV_INFO:
876 Display_Info_Reply (cont, pak, 0);
877 /* 3 unknown bytes ignored */
878
879 event->callback (event);
880 break;
881 case META_SRV_GEN:
882 Display_Info_Reply (cont, pak, 0);
883
884 if (!(mg = CONTACT_GENERAL (cont)))
885 break;
886
887 s_read (mg->city);
888 s_read (mg->state);
889 s_read (mg->phone);
890 s_read (mg->fax);
891 s_read (mg->street);
892 s_read (mg->cellular);
893 if (serv->type == TYPE_SERVER)
894 s_read (mg->zip);
895 else
896 {
897 dwdata = PacketRead4 (pak);
898 s_repl (&mg->zip, dwdata ? s_sprintf ("%ld", UD2UL (dwdata)) : "");
899 }
900 mg->country = PacketRead2 (pak);
901 mg->tz = PacketRead1 (pak);
902 mg->auth = PacketRead1 (pak);
903 /* one unknown word ignored according to v7 doc */
904 /* probably more security settings? */
905
906 cont->updated |= UPF_GENERAL_B;
907 event->callback (event);
908 break;
909 case META_SRV_MORE:
910 if (!(mm = CONTACT_MORE (cont)))
911 break;
912
913 mm->age = PacketRead2 (pak);
914 mm->sex = PacketRead1 (pak);
915 s_read (mm->homepage);
916 mm->year = PacketRead2 (pak);
917 mm->month = PacketRead1 (pak);
918 mm->day = PacketRead1 (pak);
919 mm->lang1 = PacketRead1 (pak);
920 mm->lang2 = PacketRead1 (pak);
921 mm->lang3 = PacketRead1 (pak);
922 /* one unknown word ignored according to v7 doc */
923
924 cont->updated |= UPF_MORE;
925 event->callback (event);
926 break;
927 case META_SRV_MOREEMAIL:
928 ContactMetaD (cont->meta_email);
929 cont->meta_email = NULL;
930 if ((i = PacketRead1 (pak)))
931 {
932 for (j = 0; j < i; j++)
933 {
934 int auth = PacketRead1 (pak);
935 ContactMetaAdd (&cont->meta_email, auth, ConvFromCont (PacketReadL2Str (pak, NULL), cont));
936 }
937 }
938 cont->updated |= UPF_EMAIL;
939 event->callback (event);
940 break;
941 case META_SRV_WORK:
942 if (!(mw = CONTACT_WORK (cont)))
943 break;
944
945 s_read (mw->wcity);
946 s_read (mw->wstate);
947 s_read (mw->wphone);
948 s_read (mw->wfax);
949 s_read (mw->waddress);
950 if (serv->type == TYPE_SERVER)
951 s_read (mw->wzip);
952 else
953 {
954 dwdata = PacketRead4 (pak);
955 s_repl (&mw->wzip, dwdata ? s_sprintf ("%ld", UD2UL (dwdata)) : "");
956 }
957 mw->wcountry = PacketRead2 (pak);
958 s_read (mw->wcompany);
959 s_read (mw->wdepart);
960 s_read (mw->wposition);
961 mw->woccupation = PacketRead2 (pak);
962 s_read (mw->whomepage);
963
964 cont->updated |= UPF_WORK;
965 event->callback (event);
966 break;
967 case META_SRV_ABOUT:
968 s_read (cont->meta_about);
969 cont->updated |= UPF_ABOUT;
970 event->callback (event);
971 break;
972 case META_SRV_INTEREST:
973 if (!Meta_Read_List (pak, &cont->meta_interest, cont))
974 break;
975
976 cont->updated |= UPF_INTEREST;
977 event->callback (event);
978 break;
979 case META_SRV_BACKGROUND:
980 if (!Meta_Read_List (pak, &cont->meta_background, cont))
981 break;
982 if (!Meta_Read_List (pak, &cont->meta_affiliation, cont))
983 break;
984
985 cont->updated |= UPF_BACKGROUND | UPF_AFFILIATION;
986 event->callback (event);
987 break;
988 case META_SRV_WP_FOUND:
989 case META_SRV_WP_LAST_USER:
990 if (PacketRead2 (pak) < 19)
991 {
992 rl_printf (i18n (2141, "Search %sfailed%s.\n"), COLCLIENT, COLNONE);
993 break;
994 }
995 cont = ContactUIN (serv, PacketRead4 (pak));
996 if (!cont || !(mg = CONTACT_GENERAL (cont)) || !(mm = CONTACT_MORE (cont)))
997 break;
998
999 Display_Info_Reply (cont, pak, IREP_HASAUTHFLAG);
1000 mg->webaware = PacketRead2 (pak);
1001 mm->sex = PacketRead1 (pak);
1002 mm->age = PacketRead2 (pak);
1003
1004 cont->updated |= UPF_GENERAL_C;
1005
1006 UtilUIDisplayMeta (cont);
1007 PacketRead2 (pak);
1008 if (subtype == META_SRV_WP_LAST_USER && (wdata = PacketRead2 (pak)))
1009 rl_printf ("%u %s\n", wdata, i18n (1621, "users not returned."));
1010 break;
1011 case META_SRV_RANDOM:
1012 uin = PacketRead4 (pak);
1013 event->cont = cont = ContactUIN (serv, uin);
1014 wdata = PacketRead2 (pak);
1015 rl_printf (i18n (2606, "Found random chat partner UIN %s in chat group %d.\n"),
1016 cont->screen, wdata);
1017 if (!cont || !CONTACT_DC (cont))
1018 break;
1019 if (~cont->updated & UP_INFO)
1020 {
1021 if (serv->type == TYPE_SERVER)
1022 event->seq = SnacCliMetareqinfo (serv, cont);
1023 }
1024 event->callback (event);
1025 cont->dc->ip_rem = PacketReadB4 (pak);
1026 cont->dc->port = PacketRead4 (pak);
1027 cont->dc->ip_loc = PacketReadB4 (pak);
1028 cont->dc->type = PacketRead1 (pak);
1029 cont->dc->version = PacketRead2 (pak);
1030 /* 14 unknown bytes ignored */
1031 break;
1032 case META_SRV_UNKNOWN_270:
1033 /* ignored - obsoleted as of ICQ 2002 */
1034 if (!(mo = CONTACT_OBSOLETE (cont)))
1035 break;
1036
1037 if ((mo->given = PacketRead1 (pak)))
1038 {
1039 mo->unknown = PacketReadB2 (pak);
1040 s_read (mo->description);
1041 }
1042 mo->empty = PacketRead1 (pak);
1043
1044 cont->updated |= UPF_OBSOLETE;
1045 event->callback (event);
1046 break;
1047 default:
1048 rl_printf ("%s: %s%04x%s\n",
1049 i18n (1945, "Unknown Meta User response"), COLSERVER, subtype, COLNONE);
1050 rl_print (s_dump (pak->data + pak->rpos, pak->len - pak->rpos));
1051 break;
1052 }
1053 }
1054
Display_Info_Reply(Contact * cont,Packet * pak,UBYTE flags)1055 void Display_Info_Reply (Contact *cont, Packet *pak, UBYTE flags)
1056 {
1057 MetaGeneral *mg;
1058
1059 if (!(mg = CONTACT_GENERAL (cont)))
1060 return;
1061
1062 s_read (mg->nick);
1063 s_read (mg->first);
1064 s_read (mg->last);
1065 s_read (mg->email);
1066 mg->auth = (flags & IREP_HASAUTHFLAG) ? PacketRead1 (pak) : 0;
1067
1068 cont->updated |= UPF_GENERAL_A;
1069 }
1070
Display_Ext_Info_Reply(Server * serv,Packet * pak)1071 void Display_Ext_Info_Reply (Server *serv, Packet *pak)
1072 {
1073 Contact *cont;
1074 MetaGeneral *mg;
1075 MetaMore *mm;
1076
1077 if (!(cont = ContactUIN (serv, PacketRead4 (pak))))
1078 return;
1079
1080 if (!(mg = CONTACT_GENERAL (cont)) || !(mm = CONTACT_MORE (cont)))
1081 return;
1082
1083 s_read (mg->city);
1084 mg->country = PacketRead2 (pak);
1085 mg->tz = PacketRead1 (pak);
1086 s_read (mg->state);
1087 mm->age = PacketRead2 (pak);
1088 mm->sex = PacketRead1 (pak);
1089 s_read (mg->phone);
1090 s_read (mg->fax);
1091 s_read (mm->homepage);
1092 s_read (cont->meta_about);
1093
1094 cont->updated |= UPF_GENERAL_E;
1095
1096 UtilUIDisplayMeta (cont);
1097 }
1098
Recv_Message(Server * serv,Packet * pak)1099 void Recv_Message (Server *serv, Packet *pak)
1100 {
1101 struct tm stamp;
1102 Contact *cont;
1103 strc_t ctext;
1104 const char *text;
1105 UDWORD uin;
1106 UWORD type, len;
1107
1108 uin = PacketRead4 (pak);
1109 stamp.tm_sec = 0;
1110 stamp.tm_year = PacketRead2 (pak) - 1900;
1111 stamp.tm_mon = PacketRead1 (pak) - 1;
1112 stamp.tm_mday = PacketRead1 (pak);
1113 stamp.tm_hour = PacketRead1 (pak);
1114 stamp.tm_min = PacketRead1 (pak);
1115 stamp.tm_isdst = -1;
1116 type = PacketRead2 (pak);
1117 len = PacketReadAt2 (pak, pak->rpos);
1118 ctext = PacketReadL2Str (pak, NULL);
1119
1120 cont = ContactUIN (serv, uin);
1121 if (!cont)
1122 return;
1123
1124 if (len == ctext->len + 1 && ConvIsUTF8 (ctext->txt))
1125 text = ConvFrom (ctext, ENC_UTF8)->txt;
1126 else if (len == ctext->len + 10 || len == strlen (ctext->txt) + 2)
1127 /* work around bug in Miranda < 0.3.1 */
1128 text = type == MSG_NORM ? ConvFromCont (ctext, cont) : c_in_to_split (ctext, cont);
1129 else if (len != ctext->len + 1 && type == MSG_NORM && len & 1)
1130 text = ConvFrom (ctext, ENC_UCS2BE)->txt;
1131 else
1132 text = type == MSG_NORM ? ConvFromCont (ctext, cont) : c_in_to_split (ctext, cont);
1133
1134 uiG.last_rcvd = cont;
1135 IMSrvMsg (cont, timegm (&stamp), CV_ORIGIN_v5, type, text);
1136 }
1137