// buddyicontask.cpp // Copyright (C) 2005 Matt Rogers // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301 USA #include "buddyicontask.h" #include #include #include "buffer.h" #include "connection.h" #include "transfer.h" #include "oscarutils.h" #include BuddyIconTask::BuddyIconTask( Task* parent ) :Task( parent ) { m_seq = 0; m_refNum = -1; m_iconLength = 0; m_hashType = 0; } void BuddyIconTask::uploadIcon( WORD length, const TQByteArray& data ) { m_iconLength = length; m_icon = data; m_action = Send; } void BuddyIconTask::requestIconFor( const TQString& user ) { m_user = user; m_action = Receive; } void BuddyIconTask::setHash( const TQByteArray& md5Hash ) { m_hash = md5Hash; } void BuddyIconTask::setHashType( BYTE type ) { m_hashType = type; } void BuddyIconTask::onGo() { if ( m_action == Send && m_icon.count() == 0 ) return; if ( m_action == Receive && ( m_user.isEmpty() || m_hash.count() == 0 ) ) return; if ( m_action == Receive ) { if ( client()->isIcq() ) sendICQBuddyIconRequest(); else sendAIMBuddyIconRequest(); } else sendIcon(); } bool BuddyIconTask::forMe( const Transfer* transfer ) { const SnacTransfer* st = dynamic_cast( transfer ); if ( !st ) return false; if ( st->snacRequest() != m_seq ) { kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "sequences don't match" << endl; return false; } if ( st->snacService() == 0x0010 ) { switch( st->snacSubtype() ) { case 0x0003: case 0x0005: case 0x0007: return true; break; default: return false; break; } } return false; } bool BuddyIconTask::take( Transfer* transfer ) { if ( !forMe( transfer ) ) return false; SnacTransfer* st = dynamic_cast( transfer ); if ( !st ) return false; setTransfer( transfer ); if ( st->snacSubtype() == 0x0003 ) handleUploadResponse(); else if ( st->snacSubtype() == 0x0005 ) handleAIMBuddyIconResponse(); else handleICQBuddyIconResponse(); setSuccess( 0, TQString() ); setTransfer( 0 ); return true; } void BuddyIconTask::sendIcon() { kdDebug(OSCAR_RAW_DEBUG) << "icon length: " << m_iconLength << endl; FLAP f = { 0x02, 0, 0 }; m_seq = client()->snacSequence(); SNAC s = { 0x0010, 0x0002, 0x0000, m_seq }; Buffer* b = new Buffer; b->addWord( 1 ); //pidgin hard codes it, so will we b->addWord( m_iconLength ); b->addString( m_icon ); Transfer* t = createTransfer( f, s, b ); send( t ); } void BuddyIconTask::handleUploadResponse() { kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "server acked icon upload" << endl; Buffer* b = transfer()->buffer(); b->skipBytes( 4 ); BYTE iconHashSize = b->getByte(); TQByteArray hash( b->getBlock( iconHashSize ) ); //check the hash kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "hash " << hash << endl; setSuccess( 0, TQString() ); } void BuddyIconTask::sendAIMBuddyIconRequest() { kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "requesting buddy icon for " << m_user << endl; FLAP f = { 0x02, 0, 0 }; m_seq = client()->snacSequence(); SNAC s = { 0x0010, 0x0004, 0x0000, m_seq }; Buffer* b = new Buffer; b->addBUIN( m_user.latin1() ); //TODO: check encoding b->addByte( 0x01 ); b->addWord( 0x0001 ); b->addByte( m_hashType ); b->addByte( m_hash.size() ); //MD5 Hash Size b->addString( m_hash, m_hash.size() ); //MD5 Hash Transfer* t = createTransfer( f, s, b ); send( t ); } void BuddyIconTask::handleAIMBuddyIconResponse() { Buffer* b = transfer()->buffer(); TQString user = b->getBUIN(); kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Receiving buddy icon for " << user << endl; b->skipBytes(2); //unknown field. not used BYTE iconType = b->getByte(); Q_UNUSED( iconType ); BYTE hashSize = b->getByte(); TQByteArray iconHash; iconHash.duplicate( b->getBlock(hashSize) ); WORD iconSize = b->getWord(); TQByteArray icon; icon.duplicate( b->getBlock(iconSize) ); emit haveIcon( user, icon ); } void BuddyIconTask::sendICQBuddyIconRequest() { kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "requesting buddy icon for " << m_user << endl; FLAP f = { 0x02, 0, 0 }; m_seq = client()->snacSequence(); SNAC s = { 0x0010, 0x0006, 0x0000, m_seq }; Buffer* b = new Buffer; b->addBUIN( m_user.latin1() ); //TODO: check encoding b->addByte( 0x01 ); b->addWord( 0x0001 ); b->addByte( m_hashType ); b->addByte( m_hash.size() ); //MD5 Hash Size b->addString( m_hash, m_hash.size() ); //MD5 Hash Transfer* t = createTransfer( f, s, b ); send( t ); } void BuddyIconTask::handleICQBuddyIconResponse() { Buffer* b = transfer()->buffer(); TQString user = b->getBUIN(); kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Receiving buddy icon for " << user << endl; b->skipBytes(2); //not used BYTE iconType = b->getByte(); Q_UNUSED( iconType ); BYTE hashSize = b->getByte(); TQByteArray iconHash; iconHash.duplicate( b->getBlock(hashSize) ); b->skipBytes(1); //not used b->skipBytes(2); //not used BYTE iconType2 = b->getByte(); Q_UNUSED( iconType2 ); BYTE hashSize2 = b->getByte(); TQByteArray iconHash2; iconHash2.duplicate( b->getBlock(hashSize2) ); WORD iconSize = b->getWord(); TQByteArray icon; icon.duplicate( b->getBlock(iconSize) ); emit haveIcon( user, icon ); } #include "buddyicontask.moc"