~ubuntu-branches/ubuntu/saucy/kopete/saucy-proposed

« back to all changes in this revision

Viewing changes to protocols/jabber/jabberfiletransfer.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-06-21 02:22:39 UTC
  • Revision ID: package-import@ubuntu.com-20130621022239-63l3zc8p0nf26pt6
Tags: upstream-4.10.80
ImportĀ upstreamĀ versionĀ 4.10.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 /*
 
2
  * jabberfiletransfer.cpp
 
3
  *
 
4
  * Copyright (c) 2004 by Till Gerken <till@tantalo.net>
 
5
  *
 
6
  * Kopete    (c) by the Kopete developers  <kopete-devel@kde.org>
 
7
  *
 
8
  * *************************************************************************
 
9
  * *                                                                       *
 
10
  * * This program is free software; you can redistribute it and/or modify  *
 
11
  * * it under the terms of the GNU General Public License as published by  *
 
12
  * * the Free Software Foundation; either version 2 of the License, or     *
 
13
  * * (at your option) any later version.                                   *
 
14
  * *                                                                       *
 
15
  * *************************************************************************
 
16
  */
 
17
 
 
18
#include "jabberfiletransfer.h"
 
19
#include <QBuffer>
 
20
#include <kdebug.h>
 
21
#include <im.h>
 
22
#include <xmpp.h>
 
23
#include <klocale.h>
 
24
#include <kmessagebox.h>
 
25
#include <kconfig.h>
 
26
#include <kcodecs.h>
 
27
#include "kopeteuiglobal.h"
 
28
#include "kopetemetacontact.h"
 
29
#include "kopetecontactlist.h"
 
30
#include "kopetetransfermanager.h"
 
31
#include "jabberaccount.h"
 
32
#include "jabberprotocol.h"
 
33
#include "jabberclient.h"
 
34
#include "jabbercontactpool.h"
 
35
#include "jabberbasecontact.h"
 
36
#include "jabbercontact.h"
 
37
 
 
38
JabberFileTransfer::JabberFileTransfer ( JabberAccount *account, XMPP::FileTransfer *incomingTransfer )
 
39
{
 
40
        kDebug(JABBER_DEBUG_GLOBAL) << "New incoming transfer from " << incomingTransfer->peer().full () << ", filename " << incomingTransfer->fileName () << ", size " << QString::number ( incomingTransfer->fileSize () );
 
41
 
 
42
        mAccount = account;
 
43
        mXMPPTransfer = incomingTransfer;
 
44
 
 
45
        // try to locate an exact match in our pool first
 
46
        JabberBaseContact *contact = mAccount->contactPool()->findExactMatch ( mXMPPTransfer->peer () );
 
47
 
 
48
        if ( !contact )
 
49
        {
 
50
                // we have no exact match, try a broader search
 
51
                contact = mAccount->contactPool()->findRelevantRecipient ( mXMPPTransfer->peer () );
 
52
        }
 
53
 
 
54
        if ( !contact )
 
55
        {
 
56
                kDebug(JABBER_DEBUG_GLOBAL) << "No matching local contact found, creating a new one.";
 
57
 
 
58
                Kopete::MetaContact *metaContact = new Kopete::MetaContact ();
 
59
 
 
60
                metaContact->setTemporary (true);
 
61
 
 
62
                contact = mAccount->contactPool()->addContact ( mXMPPTransfer->peer (), metaContact, false );
 
63
 
 
64
                Kopete::ContactList::self ()->addMetaContact ( metaContact );
 
65
        }
 
66
 
 
67
        connect ( Kopete::TransferManager::transferManager (), SIGNAL (accepted(Kopete::Transfer*,QString)),
 
68
                          this, SLOT (slotIncomingTransferAccepted(Kopete::Transfer*,QString)) );
 
69
        connect ( Kopete::TransferManager::transferManager (), SIGNAL (refused(Kopete::FileTransferInfo)),
 
70
                          this, SLOT (slotTransferRefused(Kopete::FileTransferInfo)) );
 
71
 
 
72
        initializeVariables ();
 
73
        
 
74
#ifdef IRIS_FILE_TRANSFER_PREVIEW
 
75
        QPixmap preview;
 
76
        if(!mXMPPTransfer->preview().isEmpty())
 
77
        {
 
78
                preview.loadFromData(KCodecs::base64Decode(mXMPPTransfer->preview().toAscii()));
 
79
        }
 
80
 
 
81
        mTransferId = Kopete::TransferManager::transferManager()->askIncomingTransfer ( contact,
 
82
                                                                                                                                                                  mXMPPTransfer->fileName (),
 
83
                                                                                                                                                                  mXMPPTransfer->fileSize (),
 
84
                                                                                                                                                                  mXMPPTransfer->description () ,
 
85
                                                                                                                                                                QString(),
 
86
                                                                                                                                                                  preview);
 
87
#endif
 
88
 
 
89
}
 
90
 
 
91
JabberFileTransfer::JabberFileTransfer ( JabberAccount *account, JabberBaseContact *contact, const QString &file )
 
92
{
 
93
        kDebug(JABBER_DEBUG_GLOBAL) << "New outgoing transfer for " << contact->contactId() << ": " << file;
 
94
 
 
95
        mAccount = account;
 
96
        mLocalFile.setFileName ( file );
 
97
        bool canOpen=mLocalFile.open ( QIODevice::ReadOnly );
 
98
        
 
99
        mKopeteTransfer = Kopete::TransferManager::transferManager()->addTransfer ( contact,
 
100
                                                                                                                                                          mLocalFile.fileName (),
 
101
                                                                                                                                                          mLocalFile.size (),
 
102
                                                                                                                                                          contact->contactId (),
 
103
                                                                                                                                                          Kopete::FileTransferInfo::Outgoing );
 
104
 
 
105
 
 
106
        connect ( mKopeteTransfer, SIGNAL (result(KJob*)), this, SLOT (slotTransferResult()) );
 
107
 
 
108
        mXMPPTransfer = mAccount->client()->fileTransferManager()->createTransfer ();
 
109
 
 
110
        initializeVariables ();
 
111
 
 
112
        connect ( mXMPPTransfer, SIGNAL (connected()), this, SLOT (slotOutgoingConnected()) );
 
113
        connect ( mXMPPTransfer, SIGNAL (bytesWritten(int)), this, SLOT (slotOutgoingBytesWritten(int)) );
 
114
        connect ( mXMPPTransfer, SIGNAL (error(int)), this, SLOT (slotTransferError(int)) );
 
115
        
 
116
        QString preview;
 
117
        QImage img=QImage(mLocalFile.fileName());
 
118
        if(!img.isNull())
 
119
        {
 
120
                img=img.scaled(64,64,Qt::KeepAspectRatio);
 
121
                QByteArray ba;
 
122
                QBuffer buffer(&ba);
 
123
                buffer.open(QIODevice::WriteOnly);
 
124
                img.save(&buffer, "PNG"); // writes image into ba in PNG format
 
125
                preview= KCodecs::base64Encode( ba  , true  );
 
126
        }
 
127
 
 
128
          
 
129
        if(canOpen) {
 
130
#ifdef IRIS_FILE_TRANSFER_PREVIEW
 
131
                mXMPPTransfer->sendFile ( XMPP::Jid ( contact->fullAddress () ), KUrl(file).fileName (), mLocalFile.size (), "", preview);
 
132
#else
 
133
                mXMPPTransfer->sendFile ( XMPP::Jid ( contact->fullAddress () ), KUrl(file).fileName (), mLocalFile.size (), "");
 
134
#endif
 
135
        } else {
 
136
                mKopeteTransfer->slotError ( KIO::ERR_CANNOT_OPEN_FOR_READING, file );
 
137
        }
 
138
 
 
139
}
 
140
 
 
141
JabberFileTransfer::~JabberFileTransfer ()
 
142
{
 
143
        kDebug(JABBER_DEBUG_GLOBAL) << "Destroying Jabber file transfer object.";
 
144
 
 
145
        mLocalFile.close ();
 
146
 
 
147
        mXMPPTransfer->close ();
 
148
        delete mXMPPTransfer;
 
149
 
 
150
}
 
151
 
 
152
void JabberFileTransfer::initializeVariables ()
 
153
{
 
154
 
 
155
        mTransferId = -1;
 
156
        mBytesTransferred = 0;
 
157
        mBytesToTransfer = 0;
 
158
        mXMPPTransfer->setProxy ( XMPP::Jid ( mAccount->configGroup()->readEntry ( "ProxyJID" ) ) );
 
159
 
 
160
}
 
161
 
 
162
void JabberFileTransfer::slotIncomingTransferAccepted ( Kopete::Transfer *transfer, const QString &fileName )
 
163
{
 
164
 
 
165
        if ( (long)transfer->info().transferId () != mTransferId )
 
166
                return;
 
167
 
 
168
        kDebug(JABBER_DEBUG_GLOBAL) << "Accepting transfer for " << mXMPPTransfer->peer().full ();
 
169
 
 
170
        mKopeteTransfer = transfer;
 
171
        mLocalFile.setFileName ( fileName );
 
172
 
 
173
        bool couldOpen = false;
 
174
        qlonglong offset = 0;
 
175
        qlonglong length = 0;
 
176
 
 
177
        mBytesTransferred = 0;
 
178
        mBytesToTransfer = mXMPPTransfer->fileSize ();
 
179
 
 
180
        if ( mXMPPTransfer->rangeSupported () && mLocalFile.exists () )
 
181
        {
 
182
                KGuiItem resumeButton ( i18n ( "&Resume" ) );
 
183
                KGuiItem overwriteButton ( i18n ( "Over&write" ) );
 
184
 
 
185
                switch ( KMessageBox::questionYesNoCancel ( Kopete::UI::Global::mainWidget (),
 
186
                                                                                                        i18n ( "The file %1 already exists, do you want to resume or overwrite it?", fileName ),
 
187
                                                                                                        i18n ( "File Exists: %1", fileName ),
 
188
                                                                                                        resumeButton, overwriteButton ) )
 
189
                {
 
190
                        case KMessageBox::Yes:          // resume
 
191
                                                                                couldOpen = mLocalFile.open ( QIODevice::ReadWrite );
 
192
                                                                                if ( couldOpen )
 
193
                                                                                {
 
194
                                                                                        offset = mLocalFile.size ();
 
195
                                                                                        length = mXMPPTransfer->fileSize () - offset;
 
196
                                                                                        mBytesTransferred = offset;
 
197
                                                                                        mBytesToTransfer = length;
 
198
                                                                                        mLocalFile.seek ( mLocalFile.size () );
 
199
                                                                                }
 
200
                                                                                break;
 
201
 
 
202
                        case KMessageBox::No:           // overwrite
 
203
                                                                                couldOpen = mLocalFile.open ( QIODevice::WriteOnly );
 
204
                                                                                break;
 
205
 
 
206
                        default:                                        // cancel
 
207
                                                                                deleteLater ();
 
208
                                                                                return;
 
209
                }
 
210
        }
 
211
        else
 
212
        {
 
213
                // overwrite by default
 
214
                couldOpen = mLocalFile.open ( QIODevice::WriteOnly );
 
215
        }
 
216
 
 
217
        if ( !couldOpen )
 
218
        {
 
219
                transfer->slotError ( KIO::ERR_COULD_NOT_WRITE, fileName );
 
220
 
 
221
                deleteLater ();
 
222
        }
 
223
        else
 
224
        {
 
225
                connect ( mKopeteTransfer, SIGNAL (result(KJob*)), this, SLOT (slotTransferResult()) );
 
226
                connect ( mXMPPTransfer, SIGNAL (readyRead(QByteArray)), this, SLOT (slotIncomingDataReady(QByteArray)) );
 
227
                connect ( mXMPPTransfer, SIGNAL (error(int)), this, SLOT (slotTransferError(int)) );
 
228
                mXMPPTransfer->accept ( offset, length );
 
229
        }
 
230
 
 
231
}
 
232
 
 
233
void JabberFileTransfer::slotTransferRefused ( const Kopete::FileTransferInfo &transfer )
 
234
{
 
235
 
 
236
        if ( (long)transfer.transferId () != mTransferId )
 
237
                return;
 
238
 
 
239
        kDebug(JABBER_DEBUG_GLOBAL) << "Local user refused transfer from " << mXMPPTransfer->peer().full ();
 
240
 
 
241
        deleteLater ();
 
242
 
 
243
}
 
244
 
 
245
void JabberFileTransfer::slotTransferResult ()
 
246
{
 
247
 
 
248
        if ( mKopeteTransfer->error () == KIO::ERR_USER_CANCELED )
 
249
        {
 
250
                kDebug(JABBER_DEBUG_GLOBAL) << "Transfer with " << mXMPPTransfer->peer().full () << " has been canceled.";
 
251
                mXMPPTransfer->close ();
 
252
                deleteLater ();
 
253
        }
 
254
 
 
255
}
 
256
 
 
257
void JabberFileTransfer::slotTransferError ( int errorCode )
 
258
{
 
259
 
 
260
        switch ( errorCode )
 
261
        {
 
262
                case XMPP::FileTransfer::ErrReject:
 
263
                        // user rejected the transfer request
 
264
                        mKopeteTransfer->slotError ( KIO::ERR_ACCESS_DENIED,
 
265
                                                                                 mXMPPTransfer->peer().full () );
 
266
                        break;
 
267
 
 
268
                case XMPP::FileTransfer::ErrNeg:
 
269
                        // unable to negotiate a suitable connection for the file transfer with the user
 
270
                        mKopeteTransfer->slotError ( KIO::ERR_COULD_NOT_LOGIN,
 
271
                                                                                 mXMPPTransfer->peer().full () );
 
272
                        break;
 
273
 
 
274
                case XMPP::FileTransfer::ErrConnect:
 
275
                        // could not connect to the user
 
276
                        mKopeteTransfer->slotError ( KIO::ERR_COULD_NOT_CONNECT,
 
277
                                                                                 mXMPPTransfer->peer().full () );
 
278
                        break;
 
279
 
 
280
                case XMPP::FileTransfer::ErrStream:
 
281
                        // data stream was disrupted, probably cancelled
 
282
                        mKopeteTransfer->slotError ( KIO::ERR_CONNECTION_BROKEN,
 
283
                                                                                 mXMPPTransfer->peer().full () );
 
284
                        break;
 
285
 
 
286
                default:
 
287
                        // unknown error
 
288
                        mKopeteTransfer->slotError ( KIO::ERR_UNKNOWN,
 
289
                                                                                 mXMPPTransfer->peer().full () );
 
290
                        break;
 
291
        }
 
292
 
 
293
        deleteLater ();
 
294
 
 
295
}
 
296
 
 
297
void JabberFileTransfer::slotIncomingDataReady ( const QByteArray &data )
 
298
{
 
299
 
 
300
        mBytesTransferred += data.size ();
 
301
        mBytesToTransfer -= data.size ();
 
302
 
 
303
        mKopeteTransfer->slotProcessed ( mBytesTransferred );
 
304
 
 
305
        mLocalFile.write ( data );
 
306
 
 
307
        if ( mBytesToTransfer <= 0 )
 
308
        {
 
309
                kDebug(JABBER_DEBUG_GLOBAL) << "Transfer from " << mXMPPTransfer->peer().full () << " done.";
 
310
 
 
311
                mKopeteTransfer->slotComplete ();
 
312
 
 
313
                deleteLater ();
 
314
        }
 
315
 
 
316
}
 
317
 
 
318
void JabberFileTransfer::slotOutgoingConnected ()
 
319
{
 
320
 
 
321
        kDebug ( JABBER_DEBUG_GLOBAL ) << "Outgoing data connection is open.";
 
322
 
 
323
        mBytesTransferred = mXMPPTransfer->offset ();
 
324
        mLocalFile.seek ( mXMPPTransfer->offset () );
 
325
        mBytesToTransfer = ( mXMPPTransfer->fileSize () > mXMPPTransfer->length () ) ? mXMPPTransfer->length () : mXMPPTransfer->fileSize ();
 
326
 
 
327
        slotOutgoingBytesWritten ( 0 );
 
328
 
 
329
}
 
330
 
 
331
void JabberFileTransfer::slotOutgoingBytesWritten ( int nrWritten )
 
332
{
 
333
 
 
334
        mBytesTransferred += nrWritten;
 
335
        mBytesToTransfer -= nrWritten;
 
336
 
 
337
        mKopeteTransfer->slotProcessed ( mBytesTransferred );
 
338
 
 
339
        if ( mBytesToTransfer )
 
340
        {
 
341
                int nrToWrite = mXMPPTransfer->dataSizeNeeded ();
 
342
 
 
343
                QByteArray readBuffer ( nrToWrite , '\0' );
 
344
 
 
345
                mLocalFile.read ( readBuffer.data (), nrToWrite );
 
346
 
 
347
                mXMPPTransfer->writeFileData ( readBuffer );
 
348
        }
 
349
        else
 
350
        {
 
351
                kDebug(JABBER_DEBUG_GLOBAL) << "Transfer to " << mXMPPTransfer->peer().full () << " done.";
 
352
 
 
353
                mKopeteTransfer->slotComplete ();
 
354
 
 
355
                deleteLater ();
 
356
        }
 
357
 
 
358
}
 
359
 
 
360
#include "jabberfiletransfer.moc"