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