1 // vim: set noet ts=4 sts=4 sw=4 :
2 // -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*-
4 // Copyright (C) 2003-2004 Grzegorz Jaskiewicz <gj at pointblue.com.pl>
5 // Copyright (C) 2003 Zack Rusin <zack@kde.org>
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 #include "gaduaccount.h"
25 #include "gaducontact.h"
26 #include "gaduprotocol.h"
28 #include "gadupubdir.h"
30 #include "gadudcctransaction.h"
32 #include "kopetemetacontact.h"
33 #include "kopetecontactlist.h"
34 #include "kopetegroup.h"
35 #include "kopetepassword.h"
36 #include "kopeteuiglobal.h"
37 #include "kopeteglobal.h"
39 #include <kpassworddialog.h>
45 #include <kmessagebox.h>
46 #include <knotification.h>
47 #include <ktemporaryfile.h>
48 #include <kactionmenu.h>
49 #include <ktoggleaction.h>
50 #include <kio/netaccess.h>
53 #include <qapplication.h>
56 #include <qtextcodec.h>
57 #include <qtextstream.h>
58 #include <qhostaddress.h>
63 #include <netinet/in.h>
64 #include <kconfiggroup.h>
66 class GaduAccountPrivate
{
69 GaduAccountPrivate() {}
71 GaduSession
* session_
;
76 QTextCodec
* textcodec_
;
77 KFileDialog
* saveListDialog
;
78 KFileDialog
* loadListDialog
;
80 KAction
* searchAction
;
81 KAction
* listputAction
;
82 KAction
* listToFileAction
;
83 KAction
* listFromFileAction
;
84 KAction
* friendsModeAction
;
88 unsigned int serverIP
;
90 QString lastDescription
;
98 Kopete::OnlineStatus status
;
99 QList
<unsigned int> servers
;
100 KGaduLoginParams loginInfo
;
104 #define USERLISTEXPORT_TIMEOUT (10*1000)
106 // FIXME: use dynamic cache please, i consider this as broken resolution of this problem
107 static const char* const servers_ip
[] = {
125 #define NUM_SERVERS (sizeof(servers_ip)/sizeof(char*))
127 GaduAccount::GaduAccount( Kopete::Protocol
* parent
, const QString
& accountID
)
128 : Kopete::PasswordedAccount( parent
, accountID
, false )
131 p
= new GaduAccountPrivate
;
133 p
->pingTimer_
= NULL
;
134 p
->saveListDialog
= NULL
;
135 p
->loadListDialog
= NULL
;
136 p
->forFriends
= false;
138 p
->textcodec_
= QTextCodec::codecForName( "CP1250" );
139 p
->session_
= new GaduSession( this );
140 p
->session_
->setObjectName( QLatin1String("GaduSession") );
142 setMyself( new GaduContact( accountId().toInt(), accountId(), this, Kopete::ContactList::self()->myself() ) );
144 p
->status
= GaduProtocol::protocol()->convertStatus( GG_STATUS_NOT_AVAIL
);
145 p
->lastDescription
.clear();
147 for ( unsigned int i
= 0; i
< NUM_SERVERS
; i
++ ) {
148 ip
.setAddress( QString( servers_ip
[i
] ) );
149 p
->servers
.append( htonl( ip
.toIPv4Address() ) );
150 kDebug( 14100 ) << "adding IP: " << p
->servers
[ i
] << " to cache";
152 p
->currentServer
= -1;
155 // initialize KGaduLogin structure to default values
156 p
->loginInfo
.uin
= accountId().toInt();
157 p
->loginInfo
.useTls
= false;
158 p
->loginInfo
.status
= GG_STATUS_AVAIL
;
159 p
->loginInfo
.server
= 0;
160 p
->loginInfo
.client_port
= 0;
161 p
->loginInfo
.client_addr
= 0;
163 p
->pingTimer_
= new QTimer( this );
164 p
->exportTimer_
= new QTimer( this );
166 p
->exportUserlist
= false;
169 p
->config
= configGroup();
171 p
->ignoreAnons
= ignoreAnons();
172 p
->forFriends
= loadFriendsMode();
177 QString nick
= p
->config
->readEntry( QString::fromAscii( "nickName" ), QString() );
178 if ( !nick
.isNull() ) {
179 myself()->setProperty( Kopete::Global::Properties::self()->nickName(), nick
);
182 myself()->setProperty( Kopete::Global::Properties::self()->nickName(), accountId() );
183 p
->config
->writeEntry( QString::fromAscii( "nickName" ), accountId() );
187 GaduAccount::~GaduAccount()
193 GaduAccount::initActions()
195 p
->searchAction
= new KAction( i18n( "&Search for Friends" ), this );
196 //, "actionSearch" );
197 QObject::connect( p
->searchAction
, SIGNAL(triggered(bool)), this, SLOT(search()) );
198 p
->listputAction
= new KAction( i18n( "Export Contacts to Server" ), this );
199 //, "actionListput" );
200 QObject::connect( p
->listputAction
, SIGNAL(triggered(bool)), this, SLOT(slotExportContactsList()) );
201 p
->listToFileAction
= new KAction( i18n( "Export Contacts to File..." ), this );
202 //, "actionListputFile" );
203 QObject::connect( p
->listToFileAction
, SIGNAL(triggered(bool)), this, SLOT(slotExportContactsListToFile()) );
204 p
->listFromFileAction
= new KAction( i18n( "Import Contacts From File..." ), this );
205 //, "actionListgetFile" );
206 QObject::connect( p
->listFromFileAction
, SIGNAL(triggered(bool)), this, SLOT(slotImportContactsFromFile()) );
207 p
->friendsModeAction
= new KToggleAction( i18n( "Only for Friends" ), this );
208 //, "actionFriendsMode" );
209 QObject::connect( p
->friendsModeAction
, SIGNAL(triggered(bool)), this, SLOT(slotFriendsMode()) );
211 static_cast<KToggleAction
*>(p
->friendsModeAction
)->setChecked( p
->forFriends
);
215 GaduAccount::initConnections()
217 QObject::connect( p
->session_
, SIGNAL( error( const QString
&, const QString
& ) ),
218 SLOT( error( const QString
&, const QString
& ) ) );
219 QObject::connect( p
->session_
, SIGNAL( messageReceived( KGaduMessage
* ) ),
220 SLOT( messageReceived( KGaduMessage
* ) ) );
221 QObject::connect( p
->session_
, SIGNAL( contactStatusChanged( KGaduNotify
* ) ),
222 SLOT( contactStatusChanged( KGaduNotify
* ) ) );
223 QObject::connect( p
->session_
, SIGNAL( connectionFailed( gg_failure_t
)),
224 SLOT( connectionFailed( gg_failure_t
) ) );
225 QObject::connect( p
->session_
, SIGNAL( connectionSucceed( ) ),
226 SLOT( connectionSucceed( ) ) );
227 QObject::connect( p
->session_
, SIGNAL( disconnect( Kopete::Account::DisconnectReason
) ),
228 SLOT( slotSessionDisconnect( Kopete::Account::DisconnectReason
) ) );
229 QObject::connect( p
->session_
, SIGNAL( ackReceived( unsigned int ) ),
230 SLOT( ackReceived( unsigned int ) ) );
231 QObject::connect( p
->session_
, SIGNAL( pubDirSearchResult( const SearchResult
&, unsigned int ) ),
232 SLOT( slotSearchResult( const SearchResult
&, unsigned int ) ) );
233 QObject::connect( p
->session_
, SIGNAL( userListExported() ),
234 SLOT( userListExportDone() ) );
235 QObject::connect( p
->session_
, SIGNAL( userListRecieved( const QString
& ) ),
236 SLOT( userlist( const QString
& ) ) );
237 QObject::connect( p
->session_
, SIGNAL( incomingCtcp( unsigned int ) ),
238 SLOT( slotIncomingDcc( unsigned int ) ) );
240 QObject::connect( p
->pingTimer_
, SIGNAL( timeout() ),
241 SLOT( pingServer() ) );
243 QObject::connect( p
->exportTimer_
, SIGNAL( timeout() ),
244 SLOT( slotUserlistSynch() ) );
248 GaduAccount::setAway( bool isAway
, const QString
& awayMessage
)
250 unsigned int currentStatus
;
253 currentStatus
= ( awayMessage
.isEmpty() ) ? GG_STATUS_BUSY
: GG_STATUS_BUSY_DESCR
;
256 currentStatus
= ( awayMessage
.isEmpty() ) ? GG_STATUS_AVAIL
: GG_STATUS_AVAIL_DESCR
;
258 changeStatus( GaduProtocol::protocol()->convertStatus( currentStatus
), awayMessage
);
263 GaduAccount::fillActionMenu( KActionMenu
*actionMenu
)
267 actionMenu
->setIcon( myself()->onlineStatus().iconFor( this ) );
268 actionMenu
->menu()->addTitle( myself()->onlineStatus().iconFor( myself() ), i18n( "%1 <%2> ",
269 myself()->property( Kopete::Global::Properties::self()->nickName()).value().toString(), accountId() ) );
271 if ( p
->session_
->isConnected() ) {
272 p
->searchAction
->setEnabled( true );
273 p
->listputAction
->setEnabled( true );
274 p
->friendsModeAction
->setEnabled( true );
277 p
->searchAction
->setEnabled( false );
278 p
->listputAction
->setEnabled( false );
279 p
->friendsModeAction
->setEnabled( false );
282 if ( contacts().count() > 1 ) {
283 if ( p
->saveListDialog
) {
284 p
->listToFileAction
->setEnabled( false );
287 p
->listToFileAction
->setEnabled( true );
290 p
->listToFileAction
->setEnabled( true );
293 p
->listToFileAction
->setEnabled( false );
296 if ( p
->loadListDialog
) {
297 p
->listFromFileAction
->setEnabled( false );
300 p
->listFromFileAction
->setEnabled( true );
303 KAction
* action
= new KAction(
304 KIcon(QIcon(GaduProtocol::protocol()->convertStatus( GG_STATUS_AVAIL
).iconFor( this ))),
305 i18n("Go O&nline"), this );
306 //, "actionGaduConnect" );
307 QObject::connect( action
, SIGNAL(triggered(bool)), this, SLOT(slotGoOnline()));
308 actionMenu
->addAction( action
);
310 action
= new KAction(
311 KIcon(QIcon(GaduProtocol::protocol()->convertStatus( GG_STATUS_BUSY
).iconFor( this ))),
312 i18n( "Set &Busy" ), this );
313 //, "actionGaduConnect" );
314 QObject::connect( action
, SIGNAL(triggered(bool)), this, SLOT(slotGoBusy()) );
315 actionMenu
->addAction( action
);
317 action
= new KAction(
318 KIcon(QIcon(GaduProtocol::protocol()->convertStatus( GG_STATUS_INVISIBLE
).iconFor( this ))),
319 i18n( "Set &Invisible" ), this );
320 //, "actionGaduConnect" );
321 QObject::connect( action
, SIGNAL(triggered(bool)), this, SLOT(slotGoInvisible()) );
322 actionMenu
->addAction( action
);
324 action
= new KAction(
325 KIcon(QIcon(GaduProtocol::protocol()->convertStatus( GG_STATUS_NOT_AVAIL
).iconFor( this ))),
326 i18n( "Go &Offline" ), this );
327 //, "actionGaduConnect" );
328 QObject::connect( action
, SIGNAL(triggered(bool)), this, SLOT(slotGoOffline()) );
329 actionMenu
->addAction( action
);
331 action
= new KAction( KIcon("edit-rename"), i18n( "Set &Description..." ), this );
332 //, "actionGaduDescription" );
333 QObject::connect( action
, SIGNAL(triggered(bool)), this, SLOT(slotDescription()) );
334 actionMenu
->addAction( action
);
336 actionMenu
->addAction( p
->friendsModeAction
);
338 actionMenu
->addSeparator();
340 actionMenu
->addAction( p
->searchAction
);
342 actionMenu
->addSeparator();
344 actionMenu
->addAction( p
->listputAction
);
346 actionMenu
->addSeparator();
348 actionMenu
->addAction( p
->listToFileAction
);
349 actionMenu
->addAction( p
->listFromFileAction
);
353 GaduAccount::hasCustomStatusMenu() const
359 GaduAccount::connectWithPassword(const QString
& password
)
361 if (password
.isEmpty()) {
366 // FIXME: add status description to this mechainsm, this is a hack now. libkopete design issue.
367 changeStatus( initialStatus(), p
->lastDescription
);
371 GaduAccount::disconnect()
373 disconnect( Manual
);
377 GaduAccount::disconnect( DisconnectReason reason
)
380 p
->connectWithSSL
= true;
381 Kopete::Account::disconnected( reason
);
385 GaduAccount::setOnlineStatus( const Kopete::OnlineStatus
& status
, const Kopete::StatusMessage
&reason
)
387 kDebug(14100) << "Called";
388 changeStatus( status
, reason
.message() );
392 GaduAccount::setStatusMessage( const Kopete::StatusMessage
& statusMessage
)
394 changeStatus( myself()->onlineStatus(), statusMessage
.message() );
398 GaduAccount::slotUserlistSynch()
400 if ( !p
->exportUserlist
) {
403 p
->exportUserlist
= false;
404 kDebug(14100) << "userlist changed, exporting";
405 slotExportContactsList();
409 GaduAccount::userlistChanged()
411 p
->exportUserlist
= true;
412 p
->exportTimer_
->start( USERLISTEXPORT_TIMEOUT
);
416 GaduAccount::createContact( const QString
& contactId
, Kopete::MetaContact
* parentContact
)
418 kDebug(14100) << "createContact " << contactId
;
420 uin_t uinNumber
= contactId
.toUInt();
421 GaduContact
* newContact
= new GaduContact( uinNumber
, parentContact
->displayName(),this, parentContact
);
422 newContact
->setParentIdentity( accountId() );
423 addNotify( uinNumber
);
431 GaduAccount::changeStatus( const Kopete::OnlineStatus
& status
, const QString
& descr
)
435 kDebug(14100) << "##### change status #####";
436 kDebug(14100) << "### Status = " << p
->session_
->isConnected();
437 kDebug(14100) << "### Status description = \"" << descr
<< "\"";
439 // if change to not available, log off
440 if ( GG_S_NA( status
.internalStatus() ) ) {
441 if ( !p
->session_
->isConnected() ) {
442 return;//already logged off
445 if ( status
.internalStatus() == GG_STATUS_NOT_AVAIL_DESCR
) {
446 if ( p
->session_
->changeStatusDescription( status
.internalStatus(), descr
, p
->forFriends
) != 0 ) {
451 p
->session_
->logoff();
455 // if status is for no desc, but we get some desc, than convert it to status with desc
456 if (!descr
.isEmpty() && !GaduProtocol::protocol()->statusWithDescription( status
.internalStatus() ) ) {
457 // and rerun us again. This won't cause any recursive call, as both conversions are static
458 ns
= GaduProtocol::protocol()->statusToWithDescription( status
);
459 changeStatus( GaduProtocol::protocol()->convertStatus( ns
), descr
);
463 // well, if it's empty but we want to set status with desc, change it too
464 if (descr
.isEmpty() && GaduProtocol::protocol()->statusWithDescription( status
.internalStatus() ) ) {
465 ns
= GaduProtocol::protocol()->statusToWithoutDescription( status
);
466 changeStatus( GaduProtocol::protocol()->convertStatus( ns
), descr
);
470 if ( !p
->session_
->isConnected() ) {
471 if ( password().cachedValue().isEmpty() ) {
472 // FIXME: when status string added to connect(), use it here
473 p
->lastDescription
= descr
;
474 connect( status
/*, descr*/ );
478 if ( useTls() != TLS_no
) {
479 p
->connectWithSSL
= true;
482 p
->connectWithSSL
= false;
486 p
->currentServer
= -1;
488 kDebug(14100) << "#### Connecting..., tls option "<< (int)useTls() << " ";
489 p
->lastDescription
= descr
;
490 slotLogin( status
.internalStatus(), descr
);
495 if ( descr
.isEmpty() ) {
496 if ( p
->session_
->changeStatus( status
.internalStatus(), p
->forFriends
) != 0 )
500 if ( p
->session_
->changeStatusDescription( status
.internalStatus(), descr
, p
->forFriends
) != 0 )
506 myself()->setOnlineStatus( status
);
507 myself()->setStatusMessage( Kopete::StatusMessage(descr
) );
509 if ( status
.internalStatus() == GG_STATUS_NOT_AVAIL
|| status
.internalStatus() == GG_STATUS_NOT_AVAIL_DESCR
) {
510 if ( p
->pingTimer_
){
511 p
->pingTimer_
->stop();
514 p
->lastDescription
= descr
;
518 GaduAccount::slotLogin( int status
, const QString
& dscr
)
520 p
->lastDescription
= dscr
;
522 myself()->setOnlineStatus( GaduProtocol::protocol()->convertStatus( GG_STATUS_CONNECTING
));
523 myself()->setStatusMessage( Kopete::StatusMessage(dscr
) );
525 if ( !p
->session_
->isConnected() ) {
526 if ( password().cachedValue().isEmpty() ) {
527 connectionFailed( GG_FAILURE_PASSWORD
);
530 p
->loginInfo
.password
= p
->textcodec_
->fromUnicode(password().cachedValue());
531 p
->loginInfo
.useTls
= p
->connectWithSSL
;
532 p
->loginInfo
.status
= status
;
533 p
->loginInfo
.statusDescr
= dscr
;
534 p
->loginInfo
.forFriends
= p
->forFriends
;
535 p
->loginInfo
.server
= p
->serverIP
;
536 if ( dccEnabled() ) {
537 p
->loginInfo
.client_addr
= gg_dcc_ip
;
538 p
->loginInfo
.client_port
= gg_dcc_port
;
541 p
->loginInfo
.client_addr
= 0;
542 p
->loginInfo
.client_port
= 0;
544 p
->session_
->login( &p
->loginInfo
);
548 p
->session_
->changeStatus( status
);
553 GaduAccount::slotLogoff()
555 if ( p
->session_
->isConnected() || p
->status
== GaduProtocol::protocol()->convertStatus( GG_STATUS_CONNECTING
)) {
556 p
->status
= GaduProtocol::protocol()->convertStatus( GG_STATUS_NOT_AVAIL
);
557 changeStatus( p
->status
);
558 p
->session_
->logoff();
564 GaduAccount::slotGoOnline()
566 changeStatus( GaduProtocol::protocol()->convertStatus( GG_STATUS_AVAIL
) );
569 GaduAccount::slotGoOffline()
576 GaduAccount::slotGoInvisible()
578 changeStatus( GaduProtocol::protocol()->convertStatus( GG_STATUS_INVISIBLE
) );
582 GaduAccount::slotGoBusy()
584 changeStatus( GaduProtocol::protocol()->convertStatus( GG_STATUS_BUSY
) );
588 GaduAccount::removeContact( const GaduContact
* c
)
590 if ( isConnected() ) {
591 const uin_t u
= c
->uin();
592 p
->session_
->removeNotify( u
);
598 GaduAccount::addNotify( uin_t uin
)
600 if ( p
->session_
->isConnected() ) {
601 p
->session_
->addNotify( uin
);
606 GaduAccount::notify( uin_t
* userlist
, int count
)
608 if ( p
->session_
->isConnected() ) {
609 p
->session_
->notify( userlist
, count
);
614 GaduAccount::sendMessage( uin_t recipient
, const Kopete::Message
& msg
, int msgClass
)
616 if ( p
->session_
->isConnected() ) {
617 p
->session_
->sendMessage( recipient
, msg
, msgClass
);
622 GaduAccount::error( const QString
& title
, const QString
& message
)
624 KMessageBox::error( Kopete::UI::Global::mainWidget(), title
, message
);
628 GaduAccount::messageReceived( KGaduMessage
* gaduMessage
)
630 GaduContact
* contact
= 0;
631 QList
<Kopete::Contact
*> contactsListTmp
;
633 // FIXME:check for ignored users list
635 if ( gaduMessage
->sender_id
== 0 ) {
636 //system message, display them or not?
637 kDebug(14100) << "####" << " System Message " << gaduMessage
->message
;
641 contact
= static_cast<GaduContact
*> ( contacts()[ QString::number( gaduMessage
->sender_id
) ] );
644 if ( p
->ignoreAnons
== true ) {
648 Kopete::MetaContact
* metaContact
= new Kopete::MetaContact ();
649 metaContact
->setTemporary ( true );
650 contact
= new GaduContact( gaduMessage
->sender_id
,
651 QString::number( gaduMessage
->sender_id
), this, metaContact
);
652 Kopete::ContactList::self ()->addMetaContact( metaContact
);
653 addNotify( gaduMessage
->sender_id
);
656 contactsListTmp
.append( myself() );
658 Kopete::Message
msg( contact
, contactsListTmp
);
659 msg
.setTimestamp( gaduMessage
->sendTime
);
660 msg
.setHtmlBody( gaduMessage
->message
);
661 msg
.setDirection( Kopete::Message::Inbound
);
663 contact
->messageReceived( msg
);
667 GaduAccount::ackReceived( unsigned int recipient
)
669 GaduContact
* contact
;
671 contact
= static_cast<GaduContact
*> ( contacts()[ QString::number( recipient
) ] );
673 kDebug(14100) << "####" << "Received an ACK from " << contact
->uin();
674 contact
->messageAck();
677 kDebug(14100) << "####" << "Received an ACK from an unknown user : " << recipient
;
682 GaduAccount::contactStatusChanged( KGaduNotify
* gaduNotify
)
684 kDebug(14100) << "####" << " contact's status changed, uin:" << gaduNotify
->contact_id
;
686 GaduContact
* contact
;
688 contact
= static_cast<GaduContact
*>( contacts()[ QString::number( gaduNotify
->contact_id
) ] );
690 kDebug(14100) << "Notify not in the list " << gaduNotify
->contact_id
;
694 contact
->changedStatus( gaduNotify
);
700 kDebug(14100) << "####" << " Pong...";
704 GaduAccount::pingServer()
706 kDebug(14100) << "####" << " Ping...";
711 GaduAccount::connectionFailed( gg_failure_t failure
)
713 bool tryReconnect
= false;
718 case GG_FAILURE_PASSWORD
:
719 password().setWrong();
720 // user pressed CANCEL
721 p
->status
= GaduProtocol::protocol()->convertStatus( GG_STATUS_NOT_AVAIL
);
722 myself()->setOnlineStatus( p
->status
);
723 disconnected( BadPassword
);
726 if ( p
->connectWithSSL
) {
727 if ( useTls() != TLS_only
) {
728 slotCommandDone( QString(), i18n( "connection using SSL was not possible, retrying without." ) );
729 kDebug( 14100 ) << "try without tls now";
730 p
->connectWithSSL
= false;
732 p
->currentServer
= -1;
738 if ( p
->currentServer
== NUM_SERVERS
- 1 ) {
740 p
->currentServer
= -1;
741 kDebug(14100) << "trying : " << "IP from hub ";
744 p
->serverIP
= p
->servers
[ ++p
->currentServer
];
745 kDebug(14100) << "trying : " << p
->currentServer
<< " IP " << p
->serverIP
;
752 if ( tryReconnect
) {
753 slotLogin( p
->status
.internalStatus() , p
->lastDescription
);
756 error( i18n( "unable to connect to the Gadu-Gadu server(\"%1\").", GaduSession::failureDescription( failure
) ),
757 i18n( "Connection Error" ) );
758 p
->status
= GaduProtocol::protocol()->convertStatus( GG_STATUS_NOT_AVAIL
);
759 myself()->setOnlineStatus( p
->status
);
760 disconnected( InvalidHost
);
767 if ( dccEnabled() ) {
768 if ( !p
->gaduDcc_
) {
769 p
->gaduDcc_
= new GaduDCC( this );
771 kDebug( 14100 ) << " turn DCC on for " << accountId();
772 p
->gaduDcc_
->registerAccount( this );
773 p
->loginInfo
.client_port
= p
->gaduDcc_
->listeingPort();
778 GaduAccount::dccOff()
781 kDebug( 14100 ) << "destroying dcc in gaduaccount ";
784 p
->loginInfo
.client_port
= 0;
785 p
->loginInfo
.client_addr
= 0;
790 GaduAccount::slotIncomingDcc( unsigned int uin
)
792 GaduContact
* contact
;
793 GaduDCCTransaction
* trans
;
799 contact
= static_cast<GaduContact
*>( contacts()[ QString::number( uin
) ] );
802 kDebug(14100) << "attempt to make dcc connection from unknown uin " << uin
;
806 // if incapabile to transfer files, forget about it.
807 if ( contact
->contactPort() < 10 ) {
808 kDebug(14100) << "can't respond to " << uin
<< " request, his listeing port is too low";
812 trans
= new GaduDCCTransaction( p
->gaduDcc_
);
813 if ( trans
->setupIncoming( p
->loginInfo
.uin
, contact
) == false ) {
820 GaduAccount::connectionSucceed( )
822 kDebug(14100) << "#### Gadu-Gadu connected! ";
823 p
->status
= GaduProtocol::protocol()->convertStatus( p
->session_
->status() );
824 myself()->setOnlineStatus( p
->status
);
825 myself()->setStatusMessage( Kopete::StatusMessage(p
->lastDescription
) );
828 p
->session_
->requestContacts();
829 p
->pingTimer_
->start( 3*60*1000 );//3 minute timeout
832 // check if we need to export userlist every USERLISTEXPORT_TIMEOUT ms
833 p
->exportTimer_
->start( USERLISTEXPORT_TIMEOUT
);
837 GaduAccount::startNotify()
840 if ( !contacts().count() ) {
845 userlist
= new uin_t
[ contacts().count() ];
847 QHashIterator
<QString
, Kopete::Contact
*> it(contacts());
848 for( i
=0 ; it
.hasNext() ; ) {
850 userlist
[i
++] = static_cast<GaduContact
*> (it
.value())->uin();
853 p
->session_
->notify( userlist
, contacts().count() );
858 GaduAccount::slotSessionDisconnect( Kopete::Account::DisconnectReason reason
)
862 kDebug(14100) << "Disconnecting";
865 p
->pingTimer_
->stop();
868 setAllContactsStatus( GaduProtocol::protocol()->convertStatus( GG_STATUS_NOT_AVAIL
) );
870 status
= myself()->onlineStatus().internalStatus();
871 if ( status
!= GG_STATUS_NOT_AVAIL
|| status
!= GG_STATUS_NOT_AVAIL_DESCR
) {
872 myself()->setOnlineStatus( GaduProtocol::protocol()->convertStatus( GG_STATUS_NOT_AVAIL
) );
874 GaduAccount::disconnect( reason
);
878 GaduAccount::userlist( const QString
& contactsListString
)
880 kDebug(14100)<<"### Got userlist - gadu account";
882 GaduContactsList
contactsList( contactsListString
);
885 GaduContact
* contact
;
886 Kopete::MetaContact
* metaContact
;
889 // don't export any new changes that were just imported :-)
890 p
->exportTimer_
->stop();
892 for ( i
= 0; i
!= contactsList
.size() ; i
++ ) {
893 kDebug(14100) << "uin " << contactsList
[i
].uin
;
895 if ( contactsList
[i
].uin
.isNull() ) {
896 kDebug(14100) << "no Uin, strange.. ";
900 if ( contacts()[ contactsList
[i
].uin
] ) {
901 kDebug(14100) << "UIN already exists in contacts "<< contactsList
[i
].uin
;
904 contactName
= GaduContact::findBestContactName( &contactsList
[i
] );
905 bool s
= addContact( contactsList
[i
].uin
, contactName
, 0L, Kopete::Account::DontChangeKABC
);
907 kDebug(14100) << "There was a problem adding UIN "<< contactsList
[i
].uin
<< "to users list";
911 contact
= static_cast<GaduContact
*>( contacts()[ contactsList
[i
].uin
] );
912 if ( contact
== NULL
) {
913 kDebug(14100) << "oops, no Kopete::Contact in contacts()[] for some reason, for \"" << contactsList
[i
].uin
<< "\"";
917 // update/add infor for contact
918 contact
->setContactDetails( &contactsList
[i
] );
920 if ( !( contactsList
[i
].group
.isEmpty() ) ) {
921 // FIXME: libkopete bug i guess, by default contact goes to top level group
922 // if user desrired to see contact somewhere else, remove it from top level one
923 metaContact
= contact
->metaContact();
924 metaContact
->removeFromGroup( Kopete::Group::topLevel() );
925 // put him in all desired groups:
926 groups
= contactsList
[i
].group
.split( ",", QString::SkipEmptyParts
);
927 for ( QStringList::Iterator groupsIterator
= groups
.begin(); groupsIterator
!= groups
.end(); ++groupsIterator
) {
928 metaContact
->addToGroup( Kopete::ContactList::self ()->findGroup ( *groupsIterator
) );
932 // start to check if we need to export userlist
933 p
->exportUserlist
= false;
934 p
->exportTimer_
->start( USERLISTEXPORT_TIMEOUT
);
938 GaduAccount::userListExportDone()
940 slotCommandDone( QString(), i18n( "Contacts exported to the server.") );
944 GaduAccount::slotFriendsMode()
946 p
->forFriends
= !p
->forFriends
;
947 kDebug( 14100 ) << "for friends mode: " << p
->forFriends
<< " desc" << p
->lastDescription
;
948 // now change status, it will changing it with p->forFriends flag
949 changeStatus( p
->status
, p
->lastDescription
);
951 saveFriendsMode( p
->forFriends
);
955 // FIXME: make loading and saving nonblocking (at the moment KFileDialog stops plugin/kopete)
958 GaduAccount::slotExportContactsListToFile()
960 KTemporaryFile tempFile
;
962 if ( p
->saveListDialog
) {
963 kDebug( 14100 ) << " save contacts to file: alread waiting for input ";
967 p
->saveListDialog
= new KFileDialog( "::kopete-gadu" + accountId(), QString(),
968 Kopete::UI::Global::mainWidget() );
969 p
->saveListDialog
->setCaption(
970 i18n("Save Contacts List for Account %1 As",
971 myself()->property( Kopete::Global::Properties::self()->nickName()).value().toString() ) );
973 if ( p
->saveListDialog
->exec() == QDialog::Accepted
) {
974 QByteArray list
= p
->textcodec_
->fromUnicode( userlist()->asString() );
976 if ( !tempFile
.open() ) {
977 // say cheese, can't create file.....
978 error( i18n( "Unable to create temporary file." ), i18n( "Save Contacts List Failed" ) );
981 QTextStream
tempStream ( &tempFile
);
982 tempStream
<< list
.data();
985 bool res
= KIO::NetAccess::upload(
986 tempFile
.fileName() ,
987 p
->saveListDialog
->selectedUrl() ,
988 Kopete::UI::Global::mainWidget()
992 error( KIO::NetAccess::lastErrorString(), i18n( "Save Contacts List Failed" ) );
997 delete p
->saveListDialog
;
998 p
->saveListDialog
= NULL
;
1002 GaduAccount::slotImportContactsFromFile()
1008 if ( p
->loadListDialog
) {
1009 kDebug( 14100 ) << "load contacts from file: alread waiting for input ";
1013 p
->loadListDialog
= new KFileDialog( "::kopete-gadu" + accountId(), QString(),
1014 Kopete::UI::Global::mainWidget() );
1015 p
->loadListDialog
->setCaption(
1016 i18n("Load Contacts List for Account %1 As",
1017 myself()->property( Kopete::Global::Properties::self()->nickName()).value().toString() ) );
1019 if ( p
->loadListDialog
->exec() == QDialog::Accepted
) {
1020 url
= p
->loadListDialog
->selectedUrl();
1021 kDebug(14100) << "a:" << url
<< "\nb:" << oname
;
1022 if ( KIO::NetAccess::download( url
, oname
, Kopete::UI::Global::mainWidget() ) ) {
1023 QFile
tempFile( oname
);
1024 if ( tempFile
.open( QIODevice::ReadOnly
) ) {
1025 list
= tempFile
.readAll();
1027 KIO::NetAccess::removeTempFile( oname
);
1029 kDebug( 14100 ) << "loaded list:";
1030 kDebug( 14100 ) << list
;
1031 kDebug( 14100 ) << " --------------- ";
1032 userlist( p
->textcodec_
->toUnicode( list
) );
1035 error( tempFile
.errorString(),
1036 i18n( "Contacts List Load Has Failed" ) );
1040 // say, it failed misourably
1041 error( KIO::NetAccess::lastErrorString(),
1042 i18n( "Contacts List Load Has Failed" ) );
1046 delete p
->loadListDialog
;
1047 p
->loadListDialog
= NULL
;
1051 GaduAccount::getPersonalInformation()
1053 return p
->session_
->getPersonalInformation();
1057 GaduAccount::publishPersonalInformation( ResLine
& d
)
1059 return p
->session_
->publishPersonalInformation( d
);
1063 GaduAccount::slotExportContactsList()
1065 p
->session_
->exportContactsOnServer( userlist() );
1069 GaduAccount::userlist()
1071 GaduContact
* contact
;
1072 GaduContactsList
* contactsList
= new GaduContactsList();
1074 if ( !contacts().count() ) {
1075 return contactsList
;
1078 QHashIterator
<QString
, Kopete::Contact
*> contactsIterator( contacts() );
1080 for( ; contactsIterator
.hasNext() ; ) {
1081 contactsIterator
.next();
1082 contact
= static_cast<GaduContact
*>( contactsIterator
.value() );
1083 if ( contact
->uin() != static_cast<GaduContact
*>( myself() )->uin() ) {
1084 contactsList
->addContact( *contact
->contactDetails() );
1088 return contactsList
;
1092 GaduAccount::slotSearch( int uin
)
1094 GaduPublicDir
* dir
= new GaduPublicDir( this, uin
);
1095 dir
->setObjectName( QLatin1String("GaduPublicDir") );
1099 GaduAccount::slotChangePassword()
1104 GaduAccount::slotCommandDone( const QString
& /*title*/, const QString
& what
)
1106 //FIXME: any chance to have my own title in event popup ?
1107 KNotification::event( KNotification::Notification
, what
);
1111 GaduAccount::slotCommandError(const QString
& title
, const QString
& what
)
1113 error( title
, what
);
1117 GaduAccount::slotDescription()
1119 GaduAway
* away
= new GaduAway( this );
1121 if( away
->exec() == QDialog::Accepted
) {
1122 changeStatus( GaduProtocol::protocol()->convertStatus( away
->status() ),
1129 GaduAccount::pubDirSearch( ResLine
& query
, int ageFrom
, int ageTo
, bool onlyAlive
)
1131 return p
->session_
->pubDirSearch( query
, ageFrom
, ageTo
, onlyAlive
);
1135 GaduAccount::pubDirSearchClose()
1137 p
->session_
->pubDirSearchClose();
1141 GaduAccount::slotSearchResult( const SearchResult
& result
, unsigned int seq
)
1143 emit
pubDirSearchResult( result
, seq
);
1147 GaduAccount::sendFile( GaduContact
* peer
, QString
& filePath
)
1149 GaduDCCTransaction
* gtran
= new GaduDCCTransaction( p
->gaduDcc_
);
1150 gtran
->setupOutgoing( peer
, filePath
);
1154 GaduAccount::dccRequest( GaduContact
* peer
)
1156 if ( peer
&& p
->session_
) {
1157 p
->session_
->dccRequest( peer
->uin() );
1163 GaduAccount::dccEnabled()
1165 QString s
= p
->config
->readEntry( QString::fromAscii( "useDcc" ), QString() );
1166 kDebug( 14100 ) << "dccEnabled: " << s
;
1167 if ( s
== QString::fromAscii( "enabled" ) ) {
1174 GaduAccount::setDcc( bool d
)
1181 s
= QString::fromAscii( "disabled" );
1184 s
= QString::fromAscii( "enabled" );
1187 p
->config
->writeEntry( QString::fromAscii( "useDcc" ), s
);
1189 if ( p
->session_
->isConnected() && d
) {
1192 kDebug( 14100 ) << "s: "<<s
;
1198 GaduAccount::saveFriendsMode( bool i
)
1200 p
->config
->writeEntry( QString::fromAscii( "forFriends" ),
1201 i
== true ? QString::fromAscii( "1" ) : QString::fromAscii( "0" ) );
1205 GaduAccount::loadFriendsMode()
1211 s
= p
->config
->readEntry( QString::fromAscii( "forFriends" ), QString() );
1222 // might be bit inconsistent with what I used in DCC, but hell, it is so much easier to parse :-)
1224 GaduAccount::ignoreAnons()
1230 s
= p
->config
->readEntry( QString( "ignoreAnons" ), QString() );
1242 GaduAccount::setIgnoreAnons( bool i
)
1245 p
->config
->writeEntry( QString::fromAscii( "ignoreAnons" ),
1246 i
== true ? QString::fromAscii( "1" ) : QString::fromAscii( "0" ) );
1249 GaduAccount::tlsConnection
1250 GaduAccount::useTls()
1257 s
= p
->config
->readEntry( QString::fromAscii( "useEncryptedConnection" ), QString() );
1258 oldC
= s
.toUInt( &c
);
1259 // we have old format
1261 kDebug( 14100 ) << "old format for param useEncryptedConnection, value " <<
1262 oldC
<< " will be converted to new string value" << endl
;
1263 setUseTls( (tlsConnection
) oldC
);
1264 // should be string now, unless there was an error reading
1265 s
= p
->config
->readEntry( QString::fromAscii( "useEncryptedConnection" ), QString() );
1266 kDebug( 14100 ) << "new useEncryptedConnection value : " << s
;
1270 if ( s
== "TLS_ifAvaliable" ) {
1271 Tls
= TLS_ifAvaliable
;
1273 if ( s
== "TLS_only" ) {
1281 GaduAccount::setUseTls( tlsConnection ut
)
1285 case TLS_ifAvaliable
:
1286 s
= "TLS_ifAvaliable";
1299 p
->config
->writeEntry( QString::fromAscii( "useEncryptedConnection" ), s
);
1302 #include "gaduaccount.moc"