source: extensions/digikam_export/piwigoexport/piwigotalker.cpp @ 4770

Last change on this file since 4770 was 4770, checked in by fcoiffie, 14 years ago

Premiere version du plugin Digikam piwigoexport

  • Connexion
  • Liste des categories
  • Upload des photos
File size: 28.1 KB
Line 
1/* ============================================================
2*
3* This file is a part of kipi-plugins project
4* http://www.kipi-plugins.org
5*
6* Date        : 2010-01-07
7* Description : a plugin to export to a remote Piwigo server.
8*
9* Copyright (C) 2003-2005 by Renchi Raju <renchi dot raju at gmail dot com>
10* Copyright (C) 2006 by Colin Guthrie <kde@colin.guthr.ie>
11* Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
12* Copyright (C) 2008 by Andrea Diamantini <adjam7 at gmail dot com>
13* Copyright (C) 2010 by Frederic Coiffier <frederic dot coiffier at free dot com>
14*
15* This program is free software; you can redistribute it
16* and/or modify it under the terms of the GNU General
17* Public License as published by the Free Software Foundation;
18* either version 2, or (at your option) any later version.
19*
20* This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23* GNU General Public License for more details.
24*
25* ============================================================ */
26
27#include "piwigotalker.h"
28#include "piwigotalker.moc"
29
30// C++ includes
31
32#include <cstring>
33#include <cstdio>
34
35// Qt includes
36
37#include <QByteArray>
38#include <QImage>
39#include <QRegExp>
40#include <QXmlStreamReader>
41#include <QFileInfo>
42#include <QCryptographicHash>
43
44// KDE includes
45
46#include <kdebug.h>
47#include <kio/job.h>
48#include <kio/jobuidelegate.h>
49#include <klocale.h>
50#include <kstandarddirs.h>
51
52// LibKExiv2 includes
53
54#include <libkexiv2/kexiv2.h>
55
56// LibKDcraw includes
57
58#include <libkdcraw/version.h>
59#include <libkdcraw/kdcraw.h>
60
61// Local includes
62
63#include "piwigoitem.h"
64#include "pluginsversion.h"
65
66namespace KIPIPiwigoExportPlugin
67{
68
69QString PiwigoTalker::s_authToken   = "";
70
71PiwigoTalker::PiwigoTalker(QWidget* parent)
72        : m_parent(parent),  m_job(0),  m_loggedIn(false)
73{
74    kDebug() << "BEGIN\n";
75}
76
77PiwigoTalker::~PiwigoTalker()
78{
79    if (m_job)
80        m_job->kill();
81}
82
83QByteArray PiwigoTalker::computeMD5Sum(const QString &filepath)
84{
85    QFile file(filepath);
86
87    file.open(QIODevice::ReadOnly);
88    QByteArray md5sum = QCryptographicHash::hash(file.readAll(), QCryptographicHash::Md5);
89    file.close();
90
91    return md5sum;
92}
93
94bool PiwigoTalker::loggedIn() const
95{
96    return m_loggedIn;
97}
98
99void PiwigoTalker::login(const KUrl& url, const QString& name, const QString& passwd)
100{
101    m_job   = 0;
102    m_url   = url;
103    m_state = GE_LOGIN;
104    m_talker_buffer.resize(0);
105
106    QString auth = name + QString(":") + passwd;
107    s_authToken = "Basic " + auth.toUtf8().toBase64();
108
109    QStringList qsl;
110    qsl.append("password=" + passwd);
111    qsl.append("method=pwg.session.login");
112    qsl.append("username=" + name);
113    QString dataParameters = qsl.join("&");
114    QByteArray buffer;
115    buffer.append(dataParameters.toUtf8());
116    m_job = KIO::http_post(m_url, buffer, KIO::HideProgressInfo);
117    m_job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
118    m_job->addMetaData("customHTTPHeader", "Authorization: " + s_authToken );
119
120    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
121            this, SLOT(slotTalkerData(KIO::Job*, const QByteArray&)));
122
123    connect(m_job, SIGNAL(result(KJob *)),
124            this, SLOT(slotResult(KJob *)));
125
126    emit signalBusy(true);
127}
128
129void PiwigoTalker::listAlbums()
130{
131    m_job   = 0;
132    m_state = GE_LISTALBUMS;
133    m_talker_buffer.resize(0);
134
135    QStringList qsl;
136    qsl.append("method=pwg.categories.getList");
137    qsl.append("recursive=true");
138    QString dataParameters = qsl.join("&");
139    QByteArray buffer;
140    buffer.append(dataParameters.toUtf8());
141
142    m_job = KIO::http_post(m_url, buffer, KIO::HideProgressInfo);
143    m_job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
144    m_job->addMetaData("customHTTPHeader", "Authorization: " + s_authToken );
145    /*    m_job->addMetaData("cookies", "manual");
146        m_job->addMetaData("setcookies", m_cookie);*/
147
148    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
149            this, SLOT(slotTalkerData(KIO::Job*, const QByteArray&)));
150
151    connect(m_job, SIGNAL(result(KJob *)),
152            this, SLOT(slotResult(KJob *)));
153
154    emit signalBusy(true);
155}
156
157void PiwigoTalker::listPhotos(const QString& albumName)
158{
159    m_job   = 0;
160    m_state = GE_LISTPHOTOS;
161    m_talker_buffer.resize(0);
162#if 0
163    PiwigoMPForm form;
164    form.addPair("cmd", "fetch-album-images");
165    form.addPair("protocol_version", "2.11");
166    form.addPair("set_albumName", albumName);
167    form.finish();
168
169    m_job = KIO::http_post(m_url, form.formData(), KIO::HideProgressInfo);
170    m_job->addMetaData("content-type", form.contentType());
171    m_job->addMetaData("cookies", "manual");
172    m_job->addMetaData("setcookies", m_cookie);
173
174    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
175            this, SLOT(slotTalkerData(KIO::Job*, const QByteArray&)));
176
177    connect(m_job, SIGNAL(result(KJob *)),
178            this, SLOT(slotResult(KJob *)));
179
180    emit signalBusy(true);
181#endif
182}
183
184void PiwigoTalker::createAlbum(const QString& parentAlbumName,
185                               const QString& albumName,
186                               const QString& albumTitle,
187                               const QString& albumCaption)
188{
189    m_job   = 0;
190    m_state = GE_CREATEALBUM;
191    m_talker_buffer.resize(0);
192#if 0
193    PiwigoMPForm form;
194    form.addPair("cmd", "new-album");
195    form.addPair("protocol_version", "2.11");
196    form.addPair("set_albumName", parentAlbumName);
197
198    if (!albumName.isEmpty())
199        form.addPair("newAlbumName", albumName);
200
201    if (!albumTitle.isEmpty())
202        form.addPair("newAlbumTitle", albumTitle);
203
204    if (!albumCaption.isEmpty())
205        form.addPair("newAlbumDesc", albumCaption);
206
207    form.finish();
208
209    m_job = KIO::http_post(m_url, form.formData(), KIO::HideProgressInfo);
210    m_job->addMetaData("content-type", form.contentType());
211    m_job->addMetaData("cookies", "manual");
212    m_job->addMetaData("setcookies", m_cookie);
213
214    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
215            this, SLOT(slotTalkerData(KIO::Job*, const QByteArray&)));
216
217    connect(m_job, SIGNAL(result(KJob*)),
218            this, SLOT(slotResult(KJob*)));
219
220    emit signalBusy(true);
221#endif
222}
223
224bool PiwigoTalker::addPhoto(int albumId,
225                            const QString& photoPath,
226                            const QString& caption,
227                            bool  captionIsTitle,
228                            bool  captionIsDescription,
229                            bool  rescale,
230                            int   maxDim,
231                            int   thumbDim)
232{
233    m_job        = 0;
234    m_state      = GE_CHECKPHOTOEXIST;
235    m_talker_buffer.resize(0);
236
237    m_path = photoPath;
238    m_albumId = albumId;
239    m_md5sum = computeMD5Sum(photoPath);
240
241    kDebug() << photoPath << " " << m_md5sum.toHex();
242
243    QImage image;
244
245    // Check if RAW file.
246    QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
247    QFileInfo fi(photoPath);
248
249    if (rawFilesExt.toUpper().contains( fi.suffix().toUpper() ))
250        KDcrawIface::KDcraw::loadDcrawPreview(image, photoPath);
251    else
252        image.load(photoPath);
253
254    if (!image.isNull()) {
255        QImage thumbnail = image.scaled(thumbDim, thumbDim, Qt::KeepAspectRatio, Qt::SmoothTransformation);
256        m_thumbpath = KStandardDirs::locateLocal("tmp", "thumb-" + KUrl(photoPath).fileName());
257        thumbnail.save(m_thumbpath, "JPEG", 80);
258        kDebug() << "Thumbnail to temp file: " << m_thumbpath ;
259
260
261        // image file - see if we need to rescale it
262        if (rescale && (image.width() > maxDim || image.height() > maxDim)) {
263            image = image.scaled(maxDim, maxDim, Qt::KeepAspectRatio, Qt::SmoothTransformation);
264        }
265
266        m_path = KStandardDirs::locateLocal("tmp", KUrl(photoPath).fileName());
267        image.save(m_path, "JPEG", 80);
268        kDebug() << "Resizing and saving to temp file: " << m_path ;
269
270        // Complete name and comment for summary sending
271        m_comment = m_name = KUrl(photoPath).fileName();
272        m_date = fi.created();
273
274        // Restore all metadata.
275        KExiv2Iface::KExiv2 exiv2Iface;
276
277        if (exiv2Iface.load(photoPath)) {
278            exiv2Iface.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
279            exiv2Iface.setImageDimensions(image.size());
280            exiv2Iface.save(m_path);
281            kDebug() << "Comment : " << exiv2Iface.getExifComment();
282            if (exiv2Iface.getExifComment().length()) {
283                if (captionIsTitle) m_name = exiv2Iface.getExifComment();
284                if (captionIsDescription) m_comment = exiv2Iface.getExifComment();
285            }
286            m_date = exiv2Iface.getImageDateTime();
287        } else {
288            kWarning() << "Image " << photoPath << " has no exif data";
289        }
290
291    } else {
292        // Invalid image
293        return false;
294    }
295
296    QStringList qsl;
297    qsl.append("method=pwg.images.exist");
298    qsl.append("md5sum_list=" + m_md5sum.toHex());
299    QString dataParameters = qsl.join("&");
300    QByteArray buffer;
301    buffer.append(dataParameters.toUtf8());
302
303    //kDebug() << "Request " << m_url << buffer << "\n";
304
305    m_job = KIO::http_post(m_url, buffer, KIO::HideProgressInfo);
306    m_job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
307    m_job->addMetaData("customHTTPHeader", "Authorization: " + s_authToken );
308    /*    m_job->addMetaData("cookies", "manual");
309        m_job->addMetaData("setcookies", m_cookie);*/
310
311    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
312            this, SLOT(slotTalkerData(KIO::Job*, const QByteArray&)));
313
314    connect(m_job, SIGNAL(result(KJob *)),
315            this, SLOT(slotResult(KJob *)));
316
317    emit signalBusy(true);
318
319    return true;
320}
321
322void PiwigoTalker::cancel()
323{
324    if (m_job) {
325        m_job->kill();
326        m_job = 0;
327    }
328}
329
330void PiwigoTalker::slotTalkerData(KIO::Job*, const QByteArray& data)
331{
332    if (data.isEmpty())
333        return;
334
335    int oldSize = m_talker_buffer.size();
336    m_talker_buffer.resize(oldSize + data.size());
337    memcpy(m_talker_buffer.data() + oldSize, data.data(), data.size());
338
339    kDebug() << data;
340}
341
342void PiwigoTalker::slotResult(KJob *job)
343{
344    KIO::Job *tempjob = static_cast<KIO::Job*>(job);
345
346    if (tempjob->error()) {
347        if (m_state == GE_LOGIN) {
348            emit signalLoginFailed(tempjob->errorString());
349            kDebug() << tempjob->errorString();
350        } else {
351            if (m_state == GE_CHECKPHOTOEXIST || m_state == GE_ADDPHOTO) {
352                emit signalAddPhotoFailed(tempjob->errorString());
353            } else {
354                tempjob->ui()->setWindow(m_parent);
355                tempjob->ui()->showErrorMessage();
356            }
357        }
358        emit signalBusy(false);
359        return;
360    }
361
362    switch (m_state) {
363    case(GE_LOGIN):
364        parseResponseLogin(m_talker_buffer);
365        break;
366    case(GE_LISTALBUMS):
367        parseResponseListAlbums(m_talker_buffer);
368        break;
369    case(GE_LISTPHOTOS):
370        parseResponseListPhotos(m_talker_buffer);
371        break;
372    case(GE_CREATEALBUM):
373        parseResponseCreateAlbum(m_talker_buffer);
374        break;
375    case(GE_CHECKPHOTOEXIST):
376        parseResponseDoesPhotoExist(m_talker_buffer);
377        break;
378    case(GE_ADDPHOTO):
379        parseResponseAddPhoto(m_talker_buffer);
380        break;
381    case(GE_ADDTHUMB):
382        parseResponseAddThumbnail(m_talker_buffer);
383        break;
384    case(GE_ADDPHOTOSUMMARY):
385        parseResponseAddPhotoSummary(m_talker_buffer);
386        break;
387    }
388
389    tempjob->kill();
390    m_job = 0;
391
392    if (m_state == GE_LOGIN && m_loggedIn) {
393        /*
394                        const QStringList cookielist = (tempjob->queryMetaData("setcookies")).split('\n');
395                m_cookie = "Cookie:";
396
397
398                if(!cookielist.isEmpty())
399                {
400                    QRegExp rx("^PIWIGOSID=.+");
401                    QString app;
402                    foreach(const QString &str, cookielist)
403                    {
404                        if(str.contains("Set-Cookie: "))
405                        {
406                            const QStringList cl = str.split(' ');
407                            int n = cl.lastIndexOf(rx);
408                            if(n!= -1)
409                            {
410                                app = cl.at(n);
411                            }
412                        }
413                    }
414                    m_cookie += app;
415                }
416        */
417        listAlbums();
418    }
419    emit signalBusy(false);
420}
421
422
423void PiwigoTalker::parseResponseLogin(const QByteArray &data)
424{
425    QXmlStreamReader ts(data);
426    QString line;
427    bool foundResponse = false;
428    m_loggedIn         = false;
429
430    while (!ts.atEnd()) {
431        ts.readNext();
432
433        if (ts.isStartElement()) {
434            foundResponse = true;
435            if (ts.name() == "rsp" && ts.attributes().value("stat") == "ok") {
436                m_loggedIn = true;
437            }
438        }
439    }
440
441    if (!foundResponse) {
442        emit signalLoginFailed(i18n("Piwigo URL probably incorrect"));
443        return;
444    }
445
446    if (!m_loggedIn) {
447        emit signalLoginFailed(i18n("Incorrect username or password specified"));
448    }
449}
450
451void PiwigoTalker::parseResponseListAlbums(const QByteArray& data)
452{
453    QString str = QString::fromUtf8(data);
454    QXmlStreamReader ts(data);
455    QString line;
456    bool foundResponse = false;
457    bool success       = false;
458
459    typedef QList<GAlbum> GAlbumList;
460    GAlbumList albumList;
461    GAlbumList::iterator iter = albumList.begin();
462
463    kDebug() << QString(data);
464
465    while (!ts.atEnd()) {
466        ts.readNext();
467
468        if (ts.isEndElement() && ts.name() == "categories")
469            break;
470
471        if (ts.isStartElement()) {
472            if (ts.name() == "rsp" && ts.attributes().value("stat") == "ok") {
473                foundResponse = true;
474            }
475            if (ts.name() == "categories") {
476                success = true;
477            }
478            if (ts.name() == "category") {
479                GAlbum album;
480                album.ref_num = ts.attributes().value("id").toString().toInt();
481                album.parent_ref_num = -1;
482                album.baseurl = ts.attributes().value("url").toString();
483
484                kDebug() << album.ref_num << " " << album.baseurl << "\n";
485
486                iter = albumList.insert(iter, album);
487            }
488            if (ts.name() == "name") {
489                (*iter).name = ts.readElementText();
490                kDebug() << (*iter).name << "\n";
491            }
492            if (ts.name() == "uppercats") {
493                QString uppercats = ts.readElementText();
494                QStringList catlist = uppercats.split(',');
495                if (catlist.size() > 1 && catlist.at(catlist.size() - 2).toInt() != (*iter).ref_num) {
496                    (*iter).parent_ref_num = catlist.at(catlist.size() - 2).toInt();
497                    kDebug() << (*iter).parent_ref_num << "\n";
498                }
499            }
500        }
501    }
502
503    if (!foundResponse) {
504        emit signalError(i18n("Invalid response received from remote Piwigo"));
505        return;
506    }
507
508    if (!success) {
509        emit signalError(i18n("Failed to list albums"));
510        return;
511    }
512
513    // We need parent albums to come first for rest of the code to work
514    qSort(albumList);
515
516    emit signalAlbums(albumList);
517}
518
519void PiwigoTalker::parseResponseListPhotos(const QByteArray &data)
520{
521    QString str = QString::fromUtf8(data);
522    QTextStream ts(&str, QIODevice::ReadOnly);
523    QString line;
524    bool foundResponse = false;
525    bool success       = false;
526
527    typedef QList<GPhoto> GPhotoList;
528    GPhotoList photoList;
529    GPhotoList::iterator iter = photoList.begin();
530
531    QString albumURL;
532
533    while (!ts.atEnd()) {
534        line = ts.readLine();
535
536        if (!foundResponse) {
537            foundResponse = line.startsWith(QLatin1String(("#__GR2PROTO__")));
538        } else {
539            QStringList strlist = line.split('=');
540            if (strlist.count() == 2) {
541                QString key   = strlist[0];
542                QString value = strlist[1];
543
544                if (key == "status") {
545                    success = (value == "0");
546                } else if (key.startsWith(QLatin1String(("image.name")))) {
547                    GPhoto photo;
548                    photo.name    = value;
549                    photo.ref_num = key.section('.', 2, 2).toInt();
550                    iter = photoList.insert(iter, photo);
551                } else if (key.startsWith(QLatin1String(("image.caption")))) {
552                    (*iter).caption = value;
553                } else if (key.startsWith(QLatin1String(("image.thumbName")))) {
554                    (*iter).thumbName = value;
555                } else if (key.startsWith(QLatin1String(("baseurl")))) {
556                    albumURL = value.replace("\\", "");     // doesn't compile fixing EBN Krazy issue!!
557                }
558            }
559        }
560    }
561
562    if (!foundResponse) {
563        emit signalError(i18n("Invalid response received from remote Piwigo"));
564        return;
565    }
566
567    if (!success) {
568        emit signalError(i18n("Failed to list photos"));
569        return;
570    }
571
572    emit signalPhotos(photoList);
573}
574
575void PiwigoTalker::parseResponseCreateAlbum(const QByteArray& data)
576{
577    QString str = QString::fromUtf8(data);
578    QTextStream ts(&str, QIODevice::ReadOnly);
579    QString line;
580    bool foundResponse = false;
581    bool success       = false;
582
583    while (!ts.atEnd()) {
584        line = ts.readLine();
585
586        if (!foundResponse) {
587            foundResponse = line.startsWith(QLatin1String(("#__GR2PROTO__")));
588        } else {
589            QStringList strlist = line.split('=');
590            if (strlist.count() == 2) {
591                QString key   = strlist[0];
592                QString value = strlist[1];
593                if (key == "status") {    // key == "status" NOT FOUND!!!
594                    success = (value == "0");
595                    kWarning() << "Create Album. success: " << success ;
596                } else if (key.startsWith(QLatin1String(("status_text")))) {
597                    kDebug() << "STATUS: Create Album: " << value ;
598                }
599            }
600        }
601    }
602
603    if (!foundResponse) {
604        emit signalError(i18n("Invalid response received from remote Piwigo"));
605        return;
606    }
607
608    if (!success) {
609        emit signalError(i18n("Failed to create new album"));
610        return;
611    }
612
613    listAlbums();
614}
615
616void PiwigoTalker::parseResponseDoesPhotoExist(const QByteArray& data)
617{
618    QString str = QString::fromUtf8(data);
619    QXmlStreamReader ts(data);
620    QString line;
621    bool foundResponse = false;
622    bool success       = false;
623
624//    typedef QList<GAlbum> GAlbumList;
625//    GAlbumList albumList;
626//    GAlbumList::iterator iter = albumList.begin();
627
628    kDebug() << QString(data);
629
630    while (!ts.atEnd()) {
631        ts.readNext();
632
633        if (ts.isStartElement()) {
634            if (ts.name() == "rsp") {
635                foundResponse = true;
636                if (ts.attributes().value("stat") == "ok") success = true;
637                break;
638            }
639        }
640    }
641
642    if (!foundResponse) {
643        emit signalAddPhotoFailed(i18n("Invalid response received from remote Piwigo"));
644        return;
645    }
646
647    if (!success) {
648        emit signalAddPhotoFailed(i18n("Failed to upload photo"));
649        return;
650    }
651
652    m_state = GE_ADDPHOTO;
653
654    QFile imagefile(m_path);
655    imagefile.open(QIODevice::ReadOnly);
656
657    QStringList qsl;
658    qsl.append("method=pwg.images.addChunk");
659    qsl.append("original_sum=" + m_md5sum.toHex());
660    qsl.append("position=1");
661    qsl.append("type=file");
662    qsl.append("data=" + imagefile.readAll().toBase64().toPercentEncoding());
663    QString dataParameters = qsl.join("&");
664    QByteArray buffer;
665    buffer.append(dataParameters.toUtf8());
666
667    imagefile.close();
668
669    //kDebug() << "Request " << m_url << buffer << "\n";
670
671    m_job = KIO::http_post(m_url, buffer, KIO::HideProgressInfo);
672    m_job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
673    m_job->addMetaData("customHTTPHeader", "Authorization: " + s_authToken );
674    /*    m_job->addMetaData("cookies", "manual");
675        m_job->addMetaData("setcookies", m_cookie);*/
676
677    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
678            this, SLOT(slotTalkerData(KIO::Job*, const QByteArray&)));
679
680    connect(m_job, SIGNAL(result(KJob *)),
681            this, SLOT(slotResult(KJob *)));
682
683#if 0
684    QString str = QString::fromUtf8(data);
685    QTextStream ts(&str, QIODevice::ReadOnly);
686    QString line;
687    bool foundResponse = false;
688    bool success       = false;
689
690    while (!ts.atEnd()) {
691        line = ts.readLine();
692
693        if (!foundResponse) {
694            // Piwigo1 sends resizing debug code sometimes so we
695            // have to detect things slightly differently
696            foundResponse = (line.startsWith(QLatin1String(("#__GR2PROTO__")))
697                             || (line.startsWith(QLatin1String(("<br>- Resizing")))
698                                 && line.endsWith(QLatin1String(("#__GR2PROTO__")))));
699        } else {
700            QStringList strlist = line.split('=');
701            if (strlist.count() == 2) {
702                QString key   = strlist[0];
703                QString value = strlist[1];
704
705                if (key == "status") {
706                    success = (value == "0");
707                    kWarning() << "Add photo. success: " << success ;
708                } else if (key.startsWith(QLatin1String(("status_text")))) {
709                    kDebug() << "STATUS: Add Photo: " << value ;
710                }
711            }
712        }
713    }
714
715    if (!foundResponse) {
716        emit signalAddPhotoFailed(i18n("Invalid response received from remote Piwigo"));
717        return;
718    }
719
720    if (!success) {
721        emit signalAddPhotoFailed(i18n("Failed to upload photo"));
722    } else {
723        emit signalAddPhotoSucceeded();
724    }
725#endif
726}
727
728
729void PiwigoTalker::parseResponseAddPhoto(const QByteArray& data)
730{
731    QString str = QString::fromUtf8(data);
732    QXmlStreamReader ts(data);
733    QString line;
734    bool foundResponse = false;
735    bool success       = false;
736
737    kDebug() << QString(data);
738
739    while (!ts.atEnd()) {
740        ts.readNext();
741
742        if (ts.isStartElement()) {
743            if (ts.name() == "rsp") {
744                foundResponse = true;
745                if (ts.attributes().value("stat") == "ok") success = true;
746                break;
747            }
748        }
749    }
750
751    if (!foundResponse) {
752        emit signalAddPhotoFailed(i18n("Invalid response received from remote Piwigo"));
753        return;
754    }
755
756    if (!success) {
757        emit signalAddPhotoFailed(i18n("Failed to upload photo"));
758        return;
759    }
760
761    m_state = GE_ADDTHUMB;
762
763    QFile imagefile(m_thumbpath);
764    imagefile.open(QIODevice::ReadOnly);
765
766    QStringList qsl;
767    qsl.append("method=pwg.images.addChunk");
768    qsl.append("original_sum=" + m_md5sum.toHex());
769    qsl.append("position=1");
770    qsl.append("type=thumb");
771    qsl.append("data=" + imagefile.readAll().toBase64().toPercentEncoding());
772    QString dataParameters = qsl.join("&");
773    QByteArray buffer;
774    buffer.append(dataParameters.toUtf8());
775
776    imagefile.close();
777
778    //kDebug() << "Request " << m_url << buffer << "\n";
779
780    m_job = KIO::http_post(m_url, buffer, KIO::HideProgressInfo);
781    m_job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
782    m_job->addMetaData("customHTTPHeader", "Authorization: " + s_authToken );
783    /*    m_job->addMetaData("cookies", "manual");
784        m_job->addMetaData("setcookies", m_cookie);*/
785
786    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
787            this, SLOT(slotTalkerData(KIO::Job*, const QByteArray&)));
788
789    connect(m_job, SIGNAL(result(KJob *)),
790            this, SLOT(slotResult(KJob *)));
791
792}
793
794void PiwigoTalker::parseResponseAddThumbnail(const QByteArray& data)
795{
796    QString str = QString::fromUtf8(data);
797    QXmlStreamReader ts(data);
798    QString line;
799    bool foundResponse = false;
800    bool success       = false;
801
802    kDebug() << QString(data);
803
804    while (!ts.atEnd()) {
805        ts.readNext();
806
807        if (ts.isStartElement()) {
808            if (ts.name() == "rsp") {
809                foundResponse = true;
810                if (ts.attributes().value("stat") == "ok") success = true;
811                break;
812            }
813        }
814    }
815
816    if (!foundResponse) {
817        emit signalAddPhotoFailed(i18n("Invalid response received from remote Piwigo"));
818        return;
819    }
820
821    if (!success) {
822        emit signalAddPhotoFailed(i18n("Failed to upload photo"));
823        return;
824    }
825
826    m_state = GE_ADDPHOTOSUMMARY;
827
828    //name=img_9738&author=Fr%E9d%E9ric+COIFFIER&categories=12&file_sum=8aa81afb8f15a5dbcf463e210e0cc6f2&thumbnail_sum=8d30dd047bd8d44ea099c461bd87ff7c&original_sum=278d66d52b278fbf531a4c7a74a0dd21&date_creation=2009%3A06%3A16&tag_ids=&comment=&mthod=pwg.images.add
829
830
831    QFile imagefile(m_thumbpath);
832    imagefile.open(QIODevice::ReadOnly);
833
834    QStringList qsl;
835    qsl.append("method=pwg.images.add");
836    qsl.append("original_sum=" + m_md5sum.toHex());
837    qsl.append("name=" + m_name.toUtf8().toPercentEncoding());
838    qsl.append("author="); // TODO
839    qsl.append("categories=" + QString::number(m_albumId));
840    qsl.append("file_sum=" + computeMD5Sum(m_path).toHex());
841    qsl.append("thumbnail_sum=" + computeMD5Sum(m_thumbpath).toHex());
842    qsl.append("date_creation=" + m_date.toString("yyyy:MM:dd").toUtf8().toPercentEncoding()); // 2007%3A06%3A23
843    qsl.append("tag_ids=");
844    qsl.append("comment=" + m_comment.toUtf8().toPercentEncoding());
845    QString dataParameters = qsl.join("&");
846    QByteArray buffer;
847    buffer.append(dataParameters.toUtf8());
848
849    imagefile.close();
850
851    kDebug() << "Request " << m_url << buffer << "\n";
852
853    m_job = KIO::http_post(m_url, buffer, KIO::HideProgressInfo);
854    m_job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
855    m_job->addMetaData("customHTTPHeader", "Authorization: " + s_authToken );
856    /*    m_job->addMetaData("cookies", "manual");
857        m_job->addMetaData("setcookies", m_cookie);*/
858
859    connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)),
860            this, SLOT(slotTalkerData(KIO::Job*, const QByteArray&)));
861
862    connect(m_job, SIGNAL(result(KJob *)),
863            this, SLOT(slotResult(KJob *)));
864}
865
866void PiwigoTalker::parseResponseAddPhotoSummary(const QByteArray& data)
867{
868    QString str = QString::fromUtf8(data);
869    QXmlStreamReader ts(data);
870    QString line;
871    bool foundResponse = false;
872    bool success       = false;
873
874    kDebug() << QString(data);
875
876    while (!ts.atEnd()) {
877        ts.readNext();
878
879        if (ts.isStartElement()) {
880            if (ts.name() == "rsp") {
881                foundResponse = true;
882                if (ts.attributes().value("stat") == "ok") success = true;
883                break;
884            }
885        }
886    }
887
888    if (!foundResponse) {
889        emit signalAddPhotoFailed(i18n("Invalid response received from remote Piwigo"));
890        return;
891    }
892
893    if (!success) {
894        emit signalAddPhotoFailed(i18n("Failed to upload photo"));
895        return;
896    }
897
898#if 0
899    while (!ts.atEnd()) {
900        line = ts.readLine();
901
902        if (!foundResponse) {
903            // Piwigo1 sends resizing debug code sometimes so we
904            // have to detect things slightly differently
905            foundResponse = (line.startsWith(QLatin1String(("#__GR2PROTO__")))
906                             || (line.startsWith(QLatin1String(("<br>- Resizing")))
907                                 && line.endsWith(QLatin1String(("#__GR2PROTO__")))));
908        } else {
909            QStringList strlist = line.split('=');
910            if (strlist.count() == 2) {
911                QString key   = strlist[0];
912                QString value = strlist[1];
913
914                if (key == "status") {
915                    success = (value == "0");
916                    kWarning() << "Add photo. success: " << success ;
917                } else if (key.startsWith(QLatin1String(("status_text")))) {
918                    kDebug() << "STATUS: Add Photo: " << value ;
919                }
920            }
921        }
922    }
923#endif
924    if (!foundResponse) {
925        emit signalAddPhotoFailed(i18n("Invalid response received from remote Piwigo"));
926        return;
927    }
928
929    if (!success) {
930        emit signalAddPhotoFailed(i18n("Failed to upload photo"));
931    } else {
932        emit signalAddPhotoSucceeded();
933    }
934}
935} // namespace KIPIPiwigoExportPlugin
Note: See TracBrowser for help on using the repository browser.