1 /*
2 	Kopete Oscar Protocol
3 	icquserinfo.h - ICQ User Info Data Types
4 
5 	Copyright (c) 2004 Matt Rogers <mattr@kde.org>
6 	Copyright (c) 2006 Roman Jarosz <kedgedev@centrum.cz>
7 
8 	Kopete (c) 2002-2006 by the Kopete developers <kopete-devel@kde.org>
9 
10 	*************************************************************************
11 	*                                                                       *
12 	* This library is free software; you can redistribute it and/or         *
13 	* modify it under the terms of the GNU Lesser General Public            *
14 	* License as published by the Free Software Foundation; either          *
15 	* version 2 of the License, or (at your option) any later version.      *
16 	*                                                                       *
17 	*************************************************************************
18 */
19 
20 #include "icquserinfo.h"
21 #include "buffer.h"
22 
23 #include <kdebug.h>
24 
ICQShortInfo()25 ICQShortInfo::ICQShortInfo()
26 {
27 	uin = 0;
28 	needsAuth.init( false );
29 	webAware.init( false );
30 }
31 
fill(Buffer * buffer)32 void ICQShortInfo::fill( Buffer* buffer )
33 {
34 	if ( buffer->getByte() == 0x0A )
35 	{
36 		kDebug(OSCAR_RAW_DEBUG) << "Parsing ICQ short user info packet";
37 		nickname = buffer->getLELNTS();
38 		firstName = buffer->getLELNTS();
39 		lastName = buffer->getLELNTS();
40 		email = buffer->getLELNTS();
41 		needsAuth = ( buffer->getByte() == 0x00 );
42 		webAware = ( buffer->getByte() != 0x02 );
43 // 		gender = buffer->getByte();
44 	}
45 	else
46 		kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ short user info packet";
47 }
48 
store(Buffer * buffer)49 void ICQShortInfo::store( Buffer* buffer )
50 {
51 	if ( needsAuth.hasChanged() )
52 	{
53 		buffer->addLETLV8( 0x02F8, ( needsAuth.get() ) ? 0x00 : 0x01 );
54 	}
55 
56 	if ( webAware.hasChanged() )
57 	{
58 		buffer->addLETLV8( 0x030C, ( webAware.get() ) ? 0x01 : 0x00 );
59 	}
60 }
61 
ICQGeneralUserInfo()62 ICQGeneralUserInfo::ICQGeneralUserInfo()
63 {
64 	uin.init( 0 );
65 	country.init( 0 );
66 	timezone.init( 0 );
67 	publishEmail.init( false );
68 	webAware.init( false );
69 	allowsDC.init( false );
70 	needsAuth.init( false );
71 }
72 
fill(Buffer * buffer)73 void ICQGeneralUserInfo::fill( Buffer* buffer )
74 {
75 	if ( buffer->getByte() == 0x0A )
76 	{
77 		kDebug(OSCAR_RAW_DEBUG) << "Parsing ICQ basic user info packet";
78 		nickName = buffer->getLELNTS();
79 		firstName = buffer->getLELNTS();
80 		lastName = buffer->getLELNTS();
81 		email = buffer->getLELNTS();
82 		city = buffer->getLELNTS();
83 		state = buffer->getLELNTS();
84 		phoneNumber = buffer->getLELNTS();
85 		faxNumber = buffer->getLELNTS();
86 		address = buffer->getLELNTS();
87 		cellNumber = buffer->getLELNTS();
88 		zip = buffer->getLELNTS();
89 		country = buffer->getLEWord();
90 		timezone = buffer->getLEByte(); // UTC+(tzcode * 30min)
91 		needsAuth = ( buffer->getByte() == 0x00 );
92 		webAware = ( buffer->getByte() == 0x01 );
93 		allowsDC = ( buffer->getByte() == 0x01 ); //taken from sim
94 		publishEmail = ( buffer->getByte() == 0x01 );
95 	}
96 	else
97 		kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ basic user info packet";
98 }
99 
store(Buffer * buffer)100 void ICQGeneralUserInfo::store( Buffer* buffer )
101 {
102 	if ( nickName.hasChanged() )
103 	{
104 		Buffer buf;
105 		buf.addLELNTS( nickName.get() );
106 		buffer->addLETLV( 0x0154, buf );
107 	}
108 	if ( firstName.hasChanged() )
109 	{
110 		Buffer buf;
111 		buf.addLELNTS( firstName.get() );
112 		buffer->addLETLV( 0x0140, buf );
113 	}
114 	if ( lastName.hasChanged() )
115 	{
116 		Buffer buf;
117 		buf.addLELNTS( lastName.get() );
118 		buffer->addLETLV( 0x014A, buf );
119 	}
120 	if ( email.hasChanged() || publishEmail.hasChanged() )
121 	{
122 		Buffer buf;
123 		buf.addLELNTS( email.get() );
124 		buf.addByte( ( publishEmail.get() ) ? 0x00 : 0x01 );
125 		buffer->addLETLV( 0x015E, buf );
126 	}
127 	if ( city.hasChanged() )
128 	{
129 		Buffer buf;
130 		buf.addLELNTS( city.get() );
131 		buffer->addLETLV( 0x0190, buf );
132 	}
133 	if ( state.hasChanged() )
134 	{
135 		Buffer buf;
136 		buf.addLELNTS( state.get() );
137 		buffer->addLETLV( 0x019A, buf );
138 	}
139 	if ( phoneNumber.hasChanged() )
140 	{
141 		Buffer buf;
142 		buf.addLELNTS( phoneNumber.get() );
143 		buffer->addLETLV( 0x0276, buf );
144 	}
145 	if ( faxNumber.hasChanged() )
146 	{
147 		Buffer buf;
148 		buf.addLELNTS( faxNumber.get() );
149 		buffer->addLETLV( 0x0280, buf );
150 	}
151 	if ( address.hasChanged() )
152 	{
153 		Buffer buf;
154 		buf.addLELNTS( address.get() );
155 		buffer->addLETLV( 0x0262, buf );
156 	}
157 	if ( cellNumber.hasChanged() )
158 	{
159 		Buffer buf;
160 		buf.addLELNTS( cellNumber.get() );
161 		buffer->addLETLV( 0x028A, buf );
162 	}
163 	if ( zip.hasChanged() )
164 	{
165 		Buffer buf;
166 		buf.addLELNTS( zip.get() );
167 		buffer->addLETLV( 0x026D, buf );
168 	}
169 	if ( country.hasChanged() )
170 	{
171 		buffer->addLETLV16( 0x01A4, country.get() );
172 	}
173 	if ( timezone.hasChanged() )
174 	{
175 		buffer->addLETLV8( 0x0316, timezone.get() );
176 	}
177 	if ( webAware.hasChanged() )
178 	{
179 		buffer->addLETLV8( 0x030C, ( webAware.get() ) ? 0x01 : 0x00 );
180 	}
181 	if ( needsAuth.hasChanged() )
182 	{
183 		buffer->addLETLV8( 0x02F8, ( needsAuth.get() ) ? 0x00 : 0x01 );
184 	}
185 }
186 
ICQWorkUserInfo()187 ICQWorkUserInfo::ICQWorkUserInfo()
188 {
189 	country.init( 0 );
190 	occupation.init( 0 );
191 }
192 
fill(Buffer * buffer)193 void ICQWorkUserInfo::fill( Buffer* buffer )
194 {
195 	if ( buffer->getByte() == 0x0A )
196 	{
197 		city = buffer->getLELNTS();
198 		state = buffer->getLELNTS();
199 		phone = buffer->getLELNTS();
200 		fax = buffer->getLELNTS();
201 		address = buffer->getLELNTS();
202 		zip = buffer->getLELNTS();
203 		country = buffer->getLEWord();
204 		company = buffer->getLELNTS();
205 		department = buffer->getLELNTS();
206 		position = buffer->getLELNTS();
207 		occupation = buffer->getLEWord();
208 		homepage = buffer->getLELNTS();
209 	}
210 	else
211 		kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ work user info packet";
212 }
213 
store(Buffer * buffer)214 void ICQWorkUserInfo::store( Buffer* buffer )
215 {
216 	if ( city.hasChanged() )
217 	{
218 		Buffer buf;
219 		buf.addLELNTS( city.get() );
220 		buffer->addLETLV( 0x029E, buf );
221 	}
222 
223 	if ( state.hasChanged() )
224 	{
225 		Buffer buf;
226 		buf.addLELNTS( state.get() );
227 		buffer->addLETLV( 0x02A8, buf );
228 	}
229 
230 	if ( phone.hasChanged() )
231 	{
232 		Buffer buf;
233 		buf.addLELNTS( phone.get() );
234 		buffer->addLETLV( 0x02C6, buf );
235 	}
236 
237 	if ( fax.hasChanged() )
238 	{
239 		Buffer buf;
240 		buf.addLELNTS( fax.get() );
241 		buffer->addLETLV( 0x02D0, buf );
242 	}
243 
244 	if ( address.hasChanged() )
245 	{
246 		Buffer buf;
247 		buf.addLELNTS( address.get() );
248 		buffer->addLETLV( 0x0294, buf );
249 	}
250 
251 	if ( zip.hasChanged() )
252 	{
253 		Buffer buf;
254 		buf.addLELNTS( zip.get() );
255 		buffer->addLETLV( 0x02BD, buf );
256 	}
257 
258 	if ( country.hasChanged() )
259 	{
260 		buffer->addLETLV16( 0x02B2, country.get() );
261 	}
262 
263 	if ( company.hasChanged() )
264 	{
265 		Buffer buf;
266 		buf.addLELNTS( company.get() );
267 		buffer->addLETLV( 0x01AE, buf );
268 	}
269 
270 	if ( department.hasChanged() )
271 	{
272 		Buffer buf;
273 		buf.addLELNTS( department.get() );
274 		buffer->addLETLV( 0x01B8, buf );
275 	}
276 
277 	if ( position.hasChanged() )
278 	{
279 		Buffer buf;
280 		buf.addLELNTS( position.get() );
281 		buffer->addLETLV( 0x01C2, buf );
282 	}
283 
284 	if ( occupation.hasChanged() )
285 	{
286 		buffer->addLETLV16( 0x01CC, occupation.get() );
287 	}
288 
289 	if ( homepage.hasChanged() )
290 	{
291 		Buffer buf;
292 		buf.addLELNTS( homepage.get() );
293 		buffer->addLETLV( 0x02DA, buf );
294 	}
295 }
296 
ICQMoreUserInfo()297 ICQMoreUserInfo::ICQMoreUserInfo()
298 {
299 	age.init( 0 );
300 	gender.init( 0 );
301 	birthdayYear.init( 0 );
302 	birthdayMonth.init( 0 );
303 	birthdayDay.init( 0 );
304 	lang1.init( 0 );
305 	lang2.init( 0 );
306 	lang3.init( 0 );
307 	ocountry.init( 0 );
308 	marital.init( 0 );
309 	sendInfo.init( false );
310 }
311 
fill(Buffer * buffer)312 void ICQMoreUserInfo::fill( Buffer* buffer )
313 {
314 	if ( buffer->getByte() == 0x0A )
315 	{
316 		age = buffer->getLEWord();
317 		gender = buffer->getByte();
318 		homepage = buffer->getLELNTS();
319 		birthdayYear = buffer->getLEWord();
320 		birthdayMonth = buffer->getByte();
321 		birthdayDay = buffer->getByte();
322 		lang1 = buffer->getByte();
323 		lang2 = buffer->getByte();
324 		lang3 = buffer->getByte();
325 		buffer->getLEWord(); //emtpy field
326 		ocity = buffer->getLELNTS();
327 		ostate = buffer->getLELNTS();
328 		ocountry = buffer->getLEWord();
329 		marital = buffer->getByte();
330 		sendInfo = buffer->getByte();
331 	}
332 	else
333 		kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ work user info packet";
334 }
335 
store(Buffer * buffer)336 void ICQMoreUserInfo::store( Buffer* buffer )
337 {
338 	if ( age.hasChanged() )
339 	{
340 		buffer->addLETLV16( 0x0172, age.get() );
341 	}
342 
343 	if ( gender.hasChanged() )
344 	{
345 		buffer->addLETLV8( 0x017C, gender.get() );
346 	}
347 
348 	if ( homepage.hasChanged() )
349 	{
350 		Buffer buf;
351 		buf.addLELNTS( homepage.get() );
352 		buffer->addLETLV( 0x0213, buf );
353 	}
354 
355 	if ( birthdayYear.hasChanged() || birthdayMonth.hasChanged() || birthdayDay.hasChanged() )
356 	{
357 		Buffer buf;
358 		buf.addLEWord( birthdayYear.get() );
359 		buf.addLEWord( birthdayMonth.get() );
360 		buf.addLEWord( birthdayDay.get() );
361 		buffer->addLETLV( 0x023A, buf );
362 	}
363 
364 	if ( lang1.hasChanged() || lang2.hasChanged() || lang3.hasChanged() )
365 	{
366 		buffer->addLETLV16( 0x0186, lang1.get() );
367 		buffer->addLETLV16( 0x0186, lang2.get() );
368 		buffer->addLETLV16( 0x0186, lang3.get() );
369 	}
370 
371 	if ( ocity.hasChanged() )
372 	{
373 		Buffer buf;
374 		buf.addLELNTS( ocity.get() );
375 		buffer->addLETLV( 0x0320, buf );
376 	}
377 
378 	if ( ostate.hasChanged() )
379 	{
380 		Buffer buf;
381 		buf.addLELNTS( ostate.get() );
382 		buffer->addLETLV( 0x032A, buf );
383 	}
384 
385 	if ( ocountry.hasChanged() )
386 	{
387 		buffer->addLETLV16( 0x0334, ocountry.get() );
388 	}
389 
390 // 	if ( marital.hasChanged() )
391 // 	{
392 // 	}
393 
394 	if ( sendInfo.hasChanged() )
395 	{
396 		buffer->addLETLV8( 0x0348, sendInfo.get() );
397 	}
398 }
399 
ICQEmailInfo()400 ICQEmailInfo::ICQEmailInfo()
401 {
402 }
403 
fill(Buffer * buffer)404 void ICQEmailInfo::fill( Buffer* buffer )
405 {
406 	if ( buffer->getByte() == 0x0A )
407 	{
408 		QList<EmailItem> emails;
409 		int numEmails = buffer->getByte();
410 		for ( int i = 0; i < numEmails; i++ )
411 		{
412 			EmailItem item;
413 			item.publish = ( buffer->getByte() == 0x00 );
414 			item.email = buffer->getLELNTS();
415 			emails.append( item );
416 		}
417 		emailList = emails;
418 	}
419 	else
420 		kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ email user info packet";
421 }
422 
store(Buffer * buffer)423 void ICQEmailInfo::store( Buffer* buffer )
424 {
425 	if ( emailList.hasChanged() )
426 	{
427 		int size = emailList.get().size();
428 		for ( int i = 0; i < size; i++ )
429 		{
430 			EmailItem item = emailList.get().at(i);
431 
432 			Buffer buf;
433 			buf.addLELNTS( item.email );
434 			buf.addByte( ( item.publish ) ? 0x00 : 0x01 );
435 			buffer->addLETLV( 0x015E, buf );
436 		}
437 	}
438 }
439 
ICQNotesInfo()440 ICQNotesInfo::ICQNotesInfo()
441 {
442 }
443 
fill(Buffer * buffer)444 void ICQNotesInfo::fill( Buffer* buffer )
445 {
446 	if ( buffer->getByte() == 0x0A )
447 		notes = buffer->getLELNTS();
448 	else
449 		kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ notes user info packet";
450 }
451 
store(Buffer * buffer)452 void ICQNotesInfo::store( Buffer* buffer )
453 {
454 	if ( notes.hasChanged() )
455 	{
456 		Buffer buf;
457 		buf.addLELNTS( notes.get() );
458 		buffer->addLETLV( 0x0258, buf );
459 	}
460 }
461 
ICQInterestInfo()462 ICQInterestInfo::ICQInterestInfo()
463 {
464 	for ( int i = 0; i < 4; i++ )
465 		topics[i].init( 0 );
466 }
467 
fill(Buffer * buffer)468 void ICQInterestInfo::fill( Buffer* buffer )
469 {
470 	if ( buffer->getByte() == 0x0A )
471 	{
472 		int count=0; //valid interests
473 		int len= buffer->getByte();  //interests we get
474 		for ( int i = 0; i < len; i++ )
475 		{
476 			int t=buffer->getLEWord();
477 			QByteArray d = buffer->getLELNTS();
478 			if (count<4) { //i think this could not happen, i have never seen more
479 				topics[count]=t;
480 				descriptions[count]=d;
481 				count++;
482 			} else {
483 				kDebug(OSCAR_RAW_DEBUG) << "got more than four interest infos";
484 			}
485 		}
486 		if ( count < 4 )
487 		{
488 			for ( int i = count; i < 4; i++ )
489 			{
490 				topics[i] = 0;
491 				descriptions[i] = QByteArray();
492 			}
493 		}
494 		kDebug(OSCAR_RAW_DEBUG) << "LEN: "<< len << " COUNT: " << count;
495 	}
496 	else
497 		kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ interest user info packet";
498 }
499 
store(Buffer * buffer)500 void ICQInterestInfo::store( Buffer* buffer )
501 {
502 	bool hasChanged = false;
503 	for ( int i = 0; i < 4; i++ )
504 	{
505 		if ( topics[i].hasChanged() || descriptions[i].hasChanged() )
506 		{
507 			hasChanged = true;
508 			break;
509 		}
510 	}
511 
512 	if ( hasChanged )
513 	{
514 		for ( int i = 0; i < 4; i++ )
515 		{
516 			if ( topics[i].get() != 0 )
517 			{
518 				Buffer buf;
519 				buf.addLEWord( topics[i].get() );
520 				buf.addLELNTS( descriptions[i].get() );
521 				buffer->addLETLV( 0x01EA, buf );
522 			}
523 		}
524 	}
525 }
526 
ICQOrgAffInfo()527 ICQOrgAffInfo::ICQOrgAffInfo()
528 {
529 	org1Category.init( 0 );
530 	org2Category.init( 0 );
531 	org3Category.init( 0 );
532 	pastAff1Category.init( 0 );
533 	pastAff2Category.init( 0 );
534 	pastAff3Category.init( 0 );
535 }
536 
fill(Buffer * buffer)537 void ICQOrgAffInfo::fill( Buffer* buffer )
538 {
539 	if ( buffer->getByte() == 0x0A )
540 	{
541 		if ( buffer->getByte() != 0x03 )
542 		{
543 			kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ affiliation info packet";
544 			return;
545 		}
546 
547 		pastAff1Category = buffer->getLEWord();
548 		pastAff1Keyword = buffer->getLELNTS();
549 		pastAff2Category = buffer->getLEWord();
550 		pastAff2Keyword = buffer->getLELNTS();
551 		pastAff3Category = buffer->getLEWord();
552 		pastAff3Keyword = buffer->getLELNTS();
553 
554 		if ( buffer->getByte() != 0x03 )
555 		{
556 			kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ organization info packet";
557 			return;
558 		}
559 
560 		org1Category = buffer->getLEWord();
561 		org1Keyword = buffer->getLELNTS();
562 		org2Category = buffer->getLEWord();
563 		org2Keyword = buffer->getLELNTS();
564 		org3Category = buffer->getLEWord();
565 		org3Keyword = buffer->getLELNTS();
566 	}
567 	else
568 		kDebug(OSCAR_RAW_DEBUG) << "Couldn't parse ICQ organization & affiliation info packet";
569 
570 }
571 
store(Buffer * buffer)572 void ICQOrgAffInfo::store( Buffer* buffer )
573 {
574 	if ( org1Category.hasChanged() || org1Keyword.hasChanged() ||
575 	     org2Category.hasChanged() || org2Keyword.hasChanged() ||
576 	     org3Category.hasChanged() || org3Keyword.hasChanged() )
577 	{
578 		if ( org1Category.get() != 0 )
579 		{
580 			Buffer buf;
581 			buf.addLEWord( org1Category.get() );
582 			buf.addLELNTS( org1Keyword.get() );
583 			buffer->addLETLV( 0x01FE, buf );
584 		}
585 
586 		if ( org2Category.get() != 0 )
587 		{
588 			Buffer buf;
589 			buf.addLEWord( org2Category.get() );
590 			buf.addLELNTS( org2Keyword.get() );
591 			buffer->addLETLV( 0x01FE, buf );
592 		}
593 
594 		if ( org3Category.get() != 0 )
595 		{
596 			Buffer buf;
597 			buf.addLEWord( org3Category.get() );
598 			buf.addLELNTS( org3Keyword.get() );
599 			buffer->addLETLV( 0x01FE, buf );
600 		}
601 	}
602 
603 	if ( pastAff1Category.hasChanged() || pastAff1Keyword.hasChanged() ||
604 	     pastAff2Category.hasChanged() || pastAff2Keyword.hasChanged() ||
605 	     pastAff3Category.hasChanged() || pastAff3Keyword.hasChanged() )
606 	{
607 		if ( pastAff1Category.get() != 0 )
608 		{
609 			Buffer buf;
610 			buf.addLEWord( pastAff1Category.get() );
611 			buf.addLELNTS( pastAff1Keyword.get() );
612 			buffer->addLETLV( 0x01D6, buf );
613 		}
614 
615 		if ( pastAff2Category.get() != 0 )
616 		{
617 			Buffer buf;
618 			buf.addLEWord( pastAff2Category.get() );
619 			buf.addLELNTS( pastAff2Keyword.get() );
620 			buffer->addLETLV( 0x01D6, buf );
621 		}
622 
623 		if ( pastAff3Category.get() != 0 )
624 		{
625 			Buffer buf;
626 			buf.addLEWord( pastAff3Category.get() );
627 			buf.addLELNTS( pastAff3Keyword.get() );
628 			buffer->addLETLV( 0x01D6, buf );
629 		}
630 	}
631 }
632 
ICQSearchResult()633 ICQSearchResult::ICQSearchResult()
634 {
635 	auth = false;
636 	online = false;
637 	gender = 'U';
638 }
639 
fill(Buffer * buffer)640 void ICQSearchResult::fill( Buffer* buffer )
641 {
642 	buffer->getLEWord(); // data length ( eat it )
643 
644 	uin = buffer->getLEDWord();
645 	kDebug(OSCAR_RAW_DEBUG) << "Found UIN " << QString::number( uin );
646 
647 	nickName = buffer->getLELNTS();
648 	firstName = buffer->getLELNTS();
649 	lastName = buffer->getLELNTS();
650 	email = buffer->getLELNTS();
651 
652 	auth = ( buffer->getByte() != 0x01 );
653 	online = ( buffer->getLEWord() == 0x0001 );
654 	switch ( buffer->getByte() )
655 	{
656 	case 0x00:
657 		gender = 'M';
658 		break;
659 	case 0x01:
660 		gender = 'F';
661 		break;
662 	default:
663 		gender = 'U';
664 		break;
665 	}
666 	age = buffer->getLEWord();
667 }
668 
ICQWPSearchInfo()669 ICQWPSearchInfo::ICQWPSearchInfo()
670 {
671 	age = 0;
672 	gender = 0;
673 	language = 0;
674 	country = 0;
675 	occupation = 0;
676 	onlineOnly = false;
677 }
678 
ICQFullInfo(bool assumeDirty)679 ICQFullInfo::ICQFullInfo( bool assumeDirty )
680 : uin(assumeDirty), firstName(assumeDirty), lastName(assumeDirty), nickName(assumeDirty),
681   homepage(assumeDirty), gender(assumeDirty), webAware(assumeDirty), privacyProfile(assumeDirty),
682   language1(assumeDirty), language2(assumeDirty), language3(assumeDirty),
683   statusDescription(assumeDirty), timezone(assumeDirty), notes(assumeDirty),
684   homeList(assumeDirty), originList(assumeDirty), workList(assumeDirty),
685   interestList(assumeDirty), organizationList(assumeDirty), pastAffliationList(assumeDirty),
686   phoneList(assumeDirty)
687 {
688 	uin.init( 0 );
689 	timezone.init( 0 );
690 }
691 
fill(Buffer * buffer)692 void ICQFullInfo::fill( Buffer* buffer )
693 {
694 	Buffer tlvListBuffer( buffer->getBSTR() );
695 	QList<TLV> tlvList = tlvListBuffer.getTLVList();
696 
697 	QList<TLV>::const_iterator it;
698 	for ( it = tlvList.constBegin(); it != tlvList.constEnd(); ++it )
699 	{
700 		switch ( (*it).type )
701 		{
702 		case 0x0032:
703 			uin = (*it).data;
704 			break;
705 		case 0x0046:
706 			break;
707 		case 0x0050:
708 			break;
709 		case 0x0055:
710 			break;
711 		case 0x0064:
712 			firstName = (*it).data;
713 			break;
714 		case 0x006e:
715 			lastName = (*it).data;
716 			break;
717 		case 0x0078:
718 			nickName = (*it).data;
719 			break;
720 		case 0x0082:
721 			{
722 			Buffer b( (*it).data );
723 			gender = b.getByte();
724 			}
725 			break;
726 		case 0x008c:
727 			break;
728 		case 0x0096:
729 			homeList = parseAddressItemList( (*it).data );
730 			break;
731 		case 0x00A0:
732 			originList = parseAddressItemList( (*it).data );
733 			break;
734 		case 0x00AA:
735 			{
736 				Buffer b( (*it).data );
737 				language1 = b.getWord();
738 			}
739 			break;
740 		case 0x00B4:
741 			{
742 				Buffer b( (*it).data );
743 				language2 = b.getWord();
744 			}
745 			break;
746 		case 0x00BE:
747 			{
748 				Buffer b( (*it).data );
749 				language3 = b.getWord();
750 			}
751 			break;
752 		case 0x00C8:
753 			phoneList = parseInfoItemList( (*it).data );
754 			break;
755 		case 0x00FA:
756 			homepage = (*it).data;
757 			break;
758 		case 0x0104:
759 			break;
760 		case 0x010e:
761 			break;
762 		case 0x0118:
763 			workList = parseWorkItemList( (*it).data );
764 			break;
765 		case 0x0122:
766 			interestList = parseInfoItemList( (*it).data );
767 			break;
768 		case 0x0123:
769 			organizationList = parseInfoItemList( (*it).data );
770 			break;
771 		case 0x0124:
772 			pastAffliationList = parseInfoItemList( (*it).data );
773 			break;
774 		case 0x012C:
775 			break;
776 		case 0x0136:
777 			break;
778 		case 0x0140:
779 			break;
780 		case 0x014A:
781 			break;
782 		case 0x0154:
783 			break;
784 		case 0x015E:
785 			break;
786 		case 0x0168:
787 			break;
788 		case 0x0172:
789 			break;
790 		case 0x017C:
791 			timezone = Buffer( (*it).data ).getWord();
792 			break;
793 		case 0x0186:
794 			notes = (*it).data;
795 			break;
796 		case 0x0190:
797 			break;
798 		case 0x019A:
799 			{
800 				Buffer b( (*it).data );
801 				webAware = (b.getWord() == 0x0001);
802 			}
803 			break;
804 		case 0x01A4:
805 			break;
806 		case 0x01AE:
807 			break;
808 		case 0x01B8:
809 			break;
810 		case 0x01C2:
811 			break;
812 		case 0x01CC:
813 			break;
814 		case 0x01D6:
815 			break;
816 		case 0x01E0:
817 			break;
818 		case 0x01EA:
819 			break;
820 		case 0x01F4:
821 			break;
822 		case 0x01F9:
823 			{
824 				Buffer b( (*it).data );
825 				privacyProfile = b.getWord();
826 			}
827 			break;
828 		case 0x01FE:
829 			break;
830 		case 0x0208:
831 			break;
832 		case 0x0212:
833 			break;
834 		case 0x021C:
835 			break;
836 		case 0x0226:
837 			statusDescription = (*it).data;
838 			break;
839 		case 0x0230:
840 			break;
841 		case 0x003C:
842 			break;
843 		default:
844 			kDebug(OSCAR_RAW_DEBUG) << "Unhandled tlv: " << hex << (*it).type << " data: " << hex << (*it).data;
845 			break;
846 		}
847 	}
848 }
849 
store(Buffer * buffer)850 void ICQFullInfo::store( Buffer* buffer )
851 {
852 	buffer->startBlock( Buffer::BWord );
853 
854 // 	if ( unknown.hasChanged() )
855 // 		buffer->addTLV( 0x0046, unknown.get() );
856 
857 // 	if ( unknown.hasChanged() )
858 // 		buffer->addTLV( 0x0050, unknown.get() );
859 
860 // 	if ( unknown.hasChanged() )
861 // 		buffer->addTLV( 0x0055, unknown.get() );
862 
863 	if ( firstName.hasChanged() )
864 		buffer->addTLV( 0x0064, firstName.get() );
865 
866 	if ( lastName.hasChanged() )
867 		buffer->addTLV( 0x006e, lastName.get() );
868 
869 	if ( nickName.hasChanged() )
870 		buffer->addTLV( 0x0078, nickName.get() );
871 
872 	if ( gender.hasChanged() )
873 		buffer->addTLV8( 0x0082, gender.get() );
874 
875 // 	if ( unknown.hasChanged() )
876 // 		buffer->addTLV( 0x008c, unknown.get() );
877 
878 	if ( homeList.hasChanged() )
879 		buffer->addTLV( 0x0096, storeAddressItemList( homeList.get() ) );
880 
881 	if ( originList.hasChanged() )
882 		buffer->addTLV( 0x00A0, storeAddressItemList( originList.get() ) );
883 
884 	if ( language1.hasChanged() )
885 		buffer->addTLV16( 0x00AA, language1.get() );
886 
887 	if ( language2.hasChanged() )
888 		buffer->addTLV16( 0x00B4, language2.get() );
889 
890 	if ( language3.hasChanged() )
891 		buffer->addTLV16( 0x00BE, language3.get() );
892 
893 	if ( phoneList.hasChanged() )
894 		buffer->addTLV( 0x00C8, storeInfoItemList( phoneList.get() ) );
895 
896 	if ( homepage.hasChanged() )
897 		buffer->addTLV( 0x00FA, homepage.get() );
898 
899 // 	if ( unknown.hasChanged() )
900 // 		buffer->addTLV( 0x0104, unknown.get() );
901 
902 // 	if ( unknown.hasChanged() )
903 // 		buffer->addTLV( 0x010e, unknown.get() );
904 
905 	if ( workList.hasChanged() )
906 		buffer->addTLV( 0x0118, storeWorkItemList( workList.get() ) );
907 
908 	if ( interestList.hasChanged() )
909 		buffer->addTLV( 0x0122, storeInfoItemList( interestList.get() ) );
910 
911 	if ( organizationList.hasChanged() )
912 		buffer->addTLV( 0x0123, storeInfoItemList( organizationList.get() ) );
913 
914 	if ( pastAffliationList.hasChanged() )
915 		buffer->addTLV( 0x0124, storeInfoItemList( pastAffliationList.get() ) );
916 
917 // 	if ( unknown.hasChanged() )
918 // 		buffer->addTLV( 0x012C, unknown.get() );
919 
920 // 	if ( unknown.hasChanged() )
921 // 		buffer->addTLV( 0x0136, unknown.get() );
922 
923 // 	if ( unknown.hasChanged() )
924 // 		buffer->addTLV( 0x0140, unknown.get() );
925 
926 // 	if ( unknown.hasChanged() )
927 // 		buffer->addTLV( 0x014A, unknown.get() );
928 
929 // 	if ( unknown.hasChanged() )
930 // 		buffer->addTLV( 0x0154, unknown.get() );
931 
932 // 	if ( unknown.hasChanged() )
933 // 		buffer->addTLV( 0x015E, unknown.get() );
934 
935 // 	if ( unknown.hasChanged() )
936 // 		buffer->addTLV( 0x0168, unknown.get() );
937 
938 // 	if ( unknown.hasChanged() )
939 // 		buffer->addTLV( 0x0172, unknown.get() );
940 
941 	if ( timezone.hasChanged() )
942 		buffer->addTLV16( 0x017C, timezone.get() );
943 
944 	if ( notes.hasChanged() )
945 		buffer->addTLV( 0x0186, notes.get() );
946 
947 // 	if ( unknown.hasChanged() )
948 // 		buffer->addTLV( 0x0190, unknown.get() );
949 
950 	if ( webAware.hasChanged() )
951 		buffer->addTLV16( 0x019A, webAware.get() ? 0x0001 : 0x0000 );
952 
953 // 	if ( unknown.hasChanged() )
954 // 		buffer->addTLV( 0x01A4, unknown.get() );
955 
956 // 	if ( unknown.hasChanged() )
957 // 		buffer->addTLV( 0x01AE, unknown.get() );
958 
959 // 	if ( unknown.hasChanged() )
960 // 		buffer->addTLV( 0x01B8, unknown.get() );
961 
962 // 	if ( unknown.hasChanged() )
963 // 		buffer->addTLV( 0x01C2, unknown.get() );
964 
965 // 	if ( unknown.hasChanged() )
966 // 		buffer->addTLV( 0x01CC, unknown.get() );
967 
968 // 	if ( unknown.hasChanged() )
969 // 		buffer->addTLV( 0x01D6, unknown.get() );
970 
971 // 	if ( unknown.hasChanged() )
972 // 		buffer->addTLV( 0x01E0, unknown.get() );
973 
974 // 	if ( unknown.hasChanged() )
975 // 		buffer->addTLV( 0x01EA, unknown.get() );
976 
977 // 	if ( unknown.hasChanged() )
978 // 		buffer->addTLV( 0x01F4, unknown.get() );
979 
980 	if ( privacyProfile.hasChanged() )
981 		buffer->addTLV16( 0x01F9, privacyProfile.get() );
982 
983 // 	if ( unknown.hasChanged() )
984 // 		buffer->addTLV( 0x01FE, unknown.get() );
985 
986 // 	if ( unknown.hasChanged() )
987 // 		buffer->addTLV( 0x0208, unknown.get() );
988 
989 // 	if ( unknown.hasChanged() )
990 // 		buffer->addTLV( 0x0212, unknown.get() );
991 
992 // 	if ( unknown.hasChanged() )
993 // 		buffer->addTLV( 0x021C, unknown.get() );
994 
995 	if ( statusDescription.hasChanged() )
996 		buffer->addTLV( 0x0226, statusDescription.get() );
997 
998 // 	if ( unknown.hasChanged() )
999 // 		buffer->addTLV( 0x0230, unknown.get() );
1000 
1001 // 	if ( unknown.hasChanged() )
1002 // 		buffer->addTLV( 0x003C, unknown.get() );
1003 
1004 	buffer->endBlock();
1005 }
1006 
parseAddressItemList(const QByteArray & data) const1007 ICQFullInfo::AddressItemList ICQFullInfo::parseAddressItemList( const QByteArray& data ) const
1008 {
1009 	Buffer buffer( data );
1010 	AddressItemList infoList;
1011 
1012 	int count = buffer.getWord();
1013 	while ( (count--) > 0 )
1014 	{
1015 		QList<TLV> tlvList = Buffer( buffer.getBSTR() ).getTLVList();
1016 
1017 		AddressItem info;
1018 		QList<TLV>::const_iterator it;
1019 		for ( it = tlvList.constBegin(); it != tlvList.constEnd(); ++it )
1020 		{
1021 			switch ( (*it).type )
1022 			{
1023 			case 0x0064:
1024 				info.address = (*it).data;
1025 				break;
1026 			case 0x006E:
1027 				info.city = (*it).data;
1028 				break;
1029 			case 0x0078:
1030 				info.state = (*it).data;
1031 				break;
1032 			case 0x0082:
1033 				info.zip = (*it).data;
1034 				break;
1035 			case 0x008C:
1036 				{
1037 					Buffer b( (*it).data );
1038 					info.country = b.getDWord();
1039 				}
1040 				break;
1041 			default:
1042 				kDebug(OSCAR_RAW_DEBUG) << "Unhandled tlv: " << hex << (*it).type << " data: " << hex << (*it).data;
1043 				break;
1044 			}
1045 		}
1046 		infoList.append( info );
1047 	}
1048 	return infoList;
1049 }
1050 
storeAddressItemList(const ICQFullInfo::AddressItemList & infoList) const1051 QByteArray ICQFullInfo::storeAddressItemList( const ICQFullInfo::AddressItemList& infoList ) const
1052 {
1053 	Buffer buffer;
1054 
1055 	buffer.addWord( infoList.count() );
1056 	for ( int i = 0; i < infoList.count(); i++ )
1057 	{
1058 		const AddressItem& info = infoList.at( i );
1059 
1060 		buffer.startBlock( Buffer::BWord );
1061 		buffer.addTLV( 0x0064, info.address );
1062 		buffer.addTLV( 0x006E, info.city );
1063 		buffer.addTLV( 0x0078, info.state );
1064 		buffer.addTLV( 0x0082, info.zip );
1065 		buffer.addTLV32( 0x008C, info.country );
1066 		buffer.endBlock();
1067 	}
1068 	return buffer.buffer();
1069 }
1070 
parseWorkItemList(const QByteArray & data) const1071 ICQFullInfo::WorkItemList ICQFullInfo::parseWorkItemList( const QByteArray& data ) const
1072 {
1073 	Buffer buffer( data );
1074 	WorkItemList infoList;
1075 
1076 	int count = buffer.getWord();
1077 	while ( (count--) > 0 )
1078 	{
1079 		QList<TLV> tlvList = Buffer( buffer.getBSTR() ).getTLVList();
1080 
1081 		WorkItem info;
1082 		QList<TLV>::const_iterator it;
1083 		for ( it = tlvList.constBegin(); it != tlvList.constEnd(); ++it )
1084 		{
1085 			switch ( (*it).type )
1086 			{
1087 			case 0x0064:
1088 				info.position = (*it).data;
1089 				break;
1090 			case 0x006E:
1091 				info.companyName = (*it).data;
1092 				break;
1093 			case 0x007D:
1094 				info.department = (*it).data;
1095 				break;
1096 			case 0x0078:
1097 				info.homepage = (*it).data;
1098 				break;
1099 			case 0x0082:
1100 				break;
1101 			case 0x008C:
1102 				break;
1103 			case 0x0096:
1104 				break;
1105 			case 0x00A0:
1106 				break;
1107 			case 0x00AA:
1108 				info.address = (*it).data;
1109 				break;
1110 			case 0x00B4:
1111 				info.city = (*it).data;
1112 				break;
1113 			case 0x00BE:
1114 				info.state = (*it).data;
1115 				break;
1116 			case 0x00C8:
1117 				info.zip = (*it).data;
1118 				break;
1119 			case 0x00D2:
1120 				{
1121 				Buffer b( (*it).data );
1122 				info.country = b.getDWord();
1123 				break;
1124 				}
1125 			default:
1126 				kDebug(OSCAR_RAW_DEBUG) << "Unhandled tlv: " << hex << (*it).type << " data: " << hex << (*it).data;
1127 				break;
1128 			}
1129 		}
1130 		infoList.append( info );
1131 	}
1132 	return infoList;
1133 }
1134 
storeWorkItemList(const ICQFullInfo::WorkItemList & infoList) const1135 QByteArray ICQFullInfo::storeWorkItemList( const ICQFullInfo::WorkItemList& infoList ) const
1136 {
1137 	Buffer buffer;
1138 
1139 	buffer.addWord( infoList.count() );
1140 	for ( int i = 0; i < infoList.count(); i++ )
1141 	{
1142 		const WorkItem& info = infoList.at( i );
1143 
1144 		buffer.startBlock( Buffer::BWord );
1145 		buffer.addTLV( 0x0064, info.position );
1146 		buffer.addTLV( 0x006E, info.companyName );
1147 		buffer.addTLV( 0x007D, info.department );
1148 		buffer.addTLV( 0x0078, info.homepage );
1149 		buffer.addTLV16( 0x0082, 0x0000 );
1150 		buffer.addTLV16( 0x008C, 0x0000 );
1151 		buffer.addTLV( 0x0096, QByteArray( 8, '\0') );
1152 		buffer.addTLV( 0x00A0, QByteArray( 8, '\0') );
1153 		buffer.addTLV( 0x00AA, info.address );
1154 		buffer.addTLV( 0x00B4, info.city );
1155 		buffer.addTLV( 0x00BE, info.state );
1156 		buffer.addTLV( 0x00C8, info.zip );
1157 		buffer.addTLV32( 0x00D2, info.country );
1158 		buffer.endBlock();
1159 	}
1160 	return buffer.buffer();
1161 }
1162 
parseInfoItemList(const QByteArray & data) const1163 ICQFullInfo::InfoItemList ICQFullInfo::parseInfoItemList( const QByteArray& data ) const
1164 {
1165 	Buffer buffer( data );
1166 	InfoItemList infoList;
1167 
1168 	int count = buffer.getWord();
1169 	while ( (count--) > 0 )
1170 	{
1171 		QList<TLV> tlvList = Buffer( buffer.getBSTR() ).getTLVList();
1172 
1173 		InfoItem info;
1174 		QList<TLV>::const_iterator it;
1175 		for ( it = tlvList.constBegin(); it != tlvList.constEnd(); ++it )
1176 		{
1177 			switch ( (*it).type )
1178 			{
1179 			case 0x0064:
1180 				info.description = (*it).data;
1181 				break;
1182 			case 0x006E:
1183 				{
1184 					Buffer b( (*it).data );
1185 					info.category = b.getWord();
1186 				}
1187 				break;
1188 			default:
1189 				kDebug(OSCAR_RAW_DEBUG) << "Unhandled tlv: " << hex << (*it).type << " data: " << hex << (*it).data;
1190 				break;
1191 			}
1192 		}
1193 		infoList.append( info );
1194 	}
1195 	return infoList;
1196 }
1197 
storeInfoItemList(const ICQFullInfo::InfoItemList & infoList) const1198 QByteArray ICQFullInfo::storeInfoItemList( const ICQFullInfo::InfoItemList& infoList ) const
1199 {
1200 	Buffer buffer;
1201 
1202 	buffer.addWord( infoList.count() );
1203 	for ( int i = 0; i < infoList.count(); i++ )
1204 	{
1205 		const InfoItem& info = infoList.at( i );
1206 
1207 		buffer.startBlock( Buffer::BWord );
1208 		buffer.addTLV( 0x0064, info.description );
1209 		buffer.addTLV16( 0x006E, info.category );
1210 		buffer.endBlock();
1211 	}
1212 	return buffer.buffer();
1213 }
1214 
1215