1 /*
2   Kopete Oscar Protocol
3   icqtlvinforequesttask.cpp - SNAC 0x15 parsing for full user info (TLV based)
4 
5   Copyright (c) 2007 Roman Jarosz <kedgedev@centrum.cz>
6 
7   Kopete (c) 2007 by the Kopete developers <kopete-devel@kde.org>
8 
9   *************************************************************************
10   *                                                                       *
11   * This library is free software; you can redistribute it and/or         *
12   * modify it under the terms of the GNU Lesser General Public            *
13   * License as published by the Free Software Foundation; either          *
14   * version 2 of the License, or (at your option) any later version.      *
15   *                                                                       *
16   *************************************************************************
17 */
18 
19 #include "icqtlvinforequesttask.h"
20 
21 #include <kdebug.h>
22 
23 #include "connection.h"
24 #include "transfer.h"
25 #include "buffer.h"
26 
ICQTlvInfoRequestTask(Task * parent)27 ICQTlvInfoRequestTask::ICQTlvInfoRequestTask( Task* parent ) : ICQTask( parent )
28 {
29 	m_type = Short;
30 }
31 
~ICQTlvInfoRequestTask()32 ICQTlvInfoRequestTask::~ICQTlvInfoRequestTask()
33 {
34 }
35 
forMe(const Transfer * transfer) const36 bool ICQTlvInfoRequestTask::forMe( const Transfer* transfer ) const
37 {
38 	const SnacTransfer * st = dynamic_cast<const SnacTransfer*>( transfer );
39 
40 	if ( !st )
41 		return false;
42 
43 	if ( st->snacService() != 0x0015 || st->snacSubtype() != 0x0003 || !m_contactSequenceMap.contains( st->snacRequest() ) )
44 		return false;
45 
46 	Buffer buf( *( st->buffer() ) );
47 	const_cast<ICQTlvInfoRequestTask*>( this )->parseInitialData( buf );
48 
49 	if ( requestType() == 0x07DA && requestSubType() == 0x0FB4 )
50 		return true;
51 
52 	return false;
53 }
54 
take(Transfer * transfer)55 bool ICQTlvInfoRequestTask::take( Transfer* transfer )
56 {
57 	if ( forMe( transfer ) )
58 	{
59 		const SnacTransfer* st = dynamic_cast<const SnacTransfer*>( transfer );
60 		if ( !st )
61 			return false;
62 
63 		setTransfer( transfer );
64 		TLV tlv1 = transfer->buffer()->getTLV();
65 		Buffer buffer( tlv1.data, tlv1.length );
66 
67 		//FIXME this is silly. parseInitialData should take care of this for me.
68 		buffer.skipBytes( 12 );
69 
70 		if ( buffer.getByte() == 0x0A )
71 		{
72 			kDebug(OSCAR_RAW_DEBUG) << "Received user info";
73 			parse( st->snacRequest(), buffer.getLEBlock() );
74 			setSuccess( 0, QString() );
75 		}
76 		else
77 		{
78 			kDebug(OSCAR_RAW_DEBUG) << "Couldn't receive user info!!!";
79 			setError( 0, QString() );
80 		}
81 
82 		setTransfer( 0 );
83 		return true;
84 	}
85 	return false;
86 }
87 
onGo()88 void ICQTlvInfoRequestTask::onGo()
89 {
90 	kDebug(OSCAR_RAW_DEBUG) << "Requsting full TLV user info for: " << m_userToRequestFor;
91 
92 	setSequence( client()->snacSequence() );
93 	setRequestType( 0x07D0 );
94 	setRequestSubType( 0x0FA0 );
95 
96 	Buffer b;
97 
98 	b.startBlock( Buffer::BWord, Buffer::LittleEndian );
99 	// Magic numbers
100 	b.addDWord( 0x05b90002 );
101 	b.addDWord( 0x80000000 );
102 	b.addDWord( 0x00000006 );
103 	b.addDWord( 0x00010002 );
104 	b.addDWord( 0x00020000 );
105 	b.addDWord( 0x04e20000 );
106 	b.addWord( 0x0002 );
107 	b.addWord( m_type );
108 	b.addDWord( 0x00000001 );
109 
110 	b.startBlock( Buffer::BWord );
111 	b.addTLV( 0x003C, m_metaInfoId );
112 	b.addTLV( 0x0032, m_userToRequestFor.toLatin1() );
113 	b.endBlock();
114 
115 	b.endBlock();
116 
117 	Buffer *sendBuf = addInitialData( &b );
118 
119 	Oscar::DWORD seq = client()->snacSequence();
120 	m_contactSequenceMap[seq] = m_userToRequestFor;
121 
122 	FLAP f = { 0x02, 0, 0 };
123 	SNAC s = { 0x0015, 0x0002, 0, seq };
124 	Transfer* t = createTransfer( f, s, sendBuf );
125 	send( t );
126 }
127 
fullInfoFor(const QString & contact)128 ICQFullInfo ICQTlvInfoRequestTask::fullInfoFor( const QString& contact )
129 {
130 	ICQFullInfo info = m_fullInfoMap.value( contact );
131 	m_fullInfoMap.remove( contact );
132 	return info;
133 }
134 
parse(Oscar::DWORD seq,const QByteArray & data)135 void ICQTlvInfoRequestTask::parse( Oscar::DWORD seq, const QByteArray &data )
136 {
137 	Buffer buf( data );
138 
139 	buf.skipBytes( 45 );
140 
141 	QString contact = m_contactSequenceMap[seq];
142 
143 	ICQFullInfo info;
144 	info.setSequenceNumber( seq );
145 	info.fill( &buf );
146 	m_fullInfoMap[contact] = info;
147 
148 	emit receivedInfoFor( contact );
149 	m_contactSequenceMap.remove( seq );
150 }
151 
152