Package: tellico
Version: 2.3.5+dfsg.1-4
Severity: wishlist
Tags: patch

Dear Maintainer,
*** Please consider answering these questions, where appropriate ***

   * What led up to the situation?
   * What exactly did you do (or not do) that was effective (or
     ineffective)?
   * What was the outcome of this action?
   * What outcome did you expect instead?

*** End of the template - remove these lines ***


-- System Information:
Debian Release: 7.1
  APT prefers stable
  APT policy: (500, 'stable')
Architecture: i386 (i686)

Kernel: Linux 3.2.0-4-686-pae (SMP w/1 CPU core)
Locale: LANG=fr_FR.UTF8, LC_CTYPE=fr_FR.UTF8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages tellico depends on:
ii  kde-runtime        4:4.8.4-2
ii  libc6              2.13-38
ii  libexempi3         2.2.0-1
ii  libgcc1            1:4.7.2-5
ii  libkabc4           4:4.8.4-2
ii  libkcal4           4:4.8.4-2
ii  libkcddb4          4:4.8.4-2
ii  libkdecore5        4:4.8.4-4
ii  libkdeui5          4:4.8.4-4
ii  libkhtml5          4:4.8.4-4
ii  libkio5            4:4.8.4-4
ii  libknewstuff3-4    4:4.8.4-4
ii  libkparts4         4:4.8.4-4
ii  libkresources4     4:4.8.4-2
ii  libksane0          4:4.8.4-1
ii  libkxmlrpcclient4  4:4.8.4-2
ii  libnepomuk4        4:4.8.4-4
ii  libpoppler-qt4-3   0.18.4-6
ii  libqimageblitz4    1:0.0.6-4
ii  libqjson0          0.7.1-7
ii  libqt4-dbus        4:4.8.2+dfsg-11
ii  libqt4-xml         4:4.8.2+dfsg-11
ii  libqtcore4         4:4.8.2+dfsg-11
ii  libqtgui4          4:4.8.2+dfsg-11
ii  libsolid4          4:4.8.4-4
ii  libstdc++6         4.7.2-5
ii  libtag1c2a         1.7.2-1
ii  libxml2            2.8.0+dfsg1-7+nmu1
ii  libxslt1.1         1.1.26-14.1
ii  libyaz4            4.2.30-2
ii  tellico-data       2.3.5+dfsg.1-4
ii  tellico-scripts    2.3.5+dfsg.1-4

Versions of packages tellico recommends:
ii  khelpcenter4  4:4.8.4-2

tellico suggests no packages.

-- no debconf information

Although kdepimlibs is an optional dependency, tellico does not compile without 
kdepimlibs5-dev. This is a knwown error and a patch is proposed by the 
upstream. I have slightly modified the patch, and I can generate the debian 
package without the kdepimlibs dependancy
Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 tellico (2.3.5+dfsg.1-4) unstable; urgency=low
 .
   * Fix passing of hardening flags. Thanks Simon Ruderich. Closes: #669190.
Author: Regis Boudin <re...@debian.org>
Bug-Debian: http://bugs.debian.org/669190

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: http://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>

--- tellico-2.3.5+dfsg.1.orig/src/fetch/CMakeLists.txt
+++ tellico-2.3.5+dfsg.1/src/fetch/CMakeLists.txt
@@ -55,7 +55,14 @@ TARGET_LINK_LIBRARIES(fetch
     btparse
     )
 
-TARGET_LINK_LIBRARIES(fetch ${KDEPIMLIBS_KXMLRPCCLIENT_LIBS})
+# Versions of KDE prior to 4.7 have a character encoding bug in libkxmlrpc
+# Use internal version of libkxmlrpc if so
+IF (KDEPIMLIBS_FOUND AND ${KDE_VERSION} VERSION_GREATER "4.6.99")
+  TARGET_LINK_LIBRARIES(fetch ${KDEPIMLIBS_KXMLRPCCLIENT_LIBS})
+ELSE (KDEPIMLIBS_FOUND AND ${KDE_VERSION} VERSION_GREATER "4.6.99")
+  ADD_SUBDIRECTORY(xmlrpc)
+  TARGET_LINK_LIBRARIES(fetch xmlrpc)
+ENDIF (KDEPIMLIBS_FOUND AND ${KDE_VERSION} VERSION_GREATER "4.6.99")
 
 IF( YAZ_FOUND )
   TARGET_LINK_LIBRARIES(fetch ${YAZ_LIBRARIES})
@@ -68,3 +75,4 @@ ENDIF( QJSON_FOUND )
 ########### install files ###############
 
 INSTALL(FILES   z3950-servers.cfg DESTINATION ${TELLICO_DATA_INSTALL_DIR} )
+
--- tellico-2.3.5+dfsg.1.orig/src/fetch/moviemeterfetcher.cpp
+++ tellico-2.3.5+dfsg.1/src/fetch/moviemeterfetcher.cpp
@@ -22,7 +22,7 @@
  *                                                                         *
  ***************************************************************************/
 
-#include <config.h>
+#include "config.h"
 #include "moviemeterfetcher.h"
 #include "../collections/videocollection.h"
 #include "../images/imagefactory.h"
@@ -40,7 +40,15 @@
 #include <QGridLayout>
 #include <QTextCodec>
 
+// we use an internal copy of kxmlrpc for versions before 4.7
+// since it doesn't handle character encoding correctly
+// see https://git.reviewboard.kde.org/r/101838/
+#include <kdeversion.h>
+#if defined(HAVE_KXMLRPC) && KDE_IS_VERSION(4,7,0)
 #include <kxmlrpcclient/client.h>
+#else
+#include "xmlrpc/client.h"
+#endif
 
 namespace {
   static const char* MOVIEMETER_API_KEY = "t80a06uf736d0yd00jpynpdsgea255yk";
@@ -371,3 +379,4 @@ QString MovieMeterFetcher::ConfigWidget:
 }
 
 #include "moviemeterfetcher.moc"
+
--- /dev/null
+++ tellico-2.3.5+dfsg.1/src/fetch/xmlrpc/query.h
@@ -0,0 +1,103 @@
+/******************************************************************************
+ *   Copyright (C) 2003 - 2004 by Frerich Raabe <ra...@kde.org>               *
+ *                                Tobias Koenig <to...@kde.org>               *
+ *   Copyright (C) 2006 by Narayan Newton <narayannew...@gmail.com>           *
+ *                                                                            *
+ * This program 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. For licensing and distribution        *
+ * details, check the accompanying file 'COPYING.BSD'.                        *
+ *****************************************************************************/
+/**
+  @file
+
+  This file is part of KXmlRpc and defines our internal classes.
+
+  @author Frerich Raabe <ra...@kde.org>
+  @author Tobias Koenig <to...@kde.org>
+  @author Narayan Newton <narayannew...@gmail.com>
+*/
+
+#ifndef KXML_RPC_QUERY_H
+#define KXML_RPC_QUERY_H
+
+#undef QT_NO_CAST_FROM_ASCII
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QVariant>
+#include <QtCore/QMap>
+#include <kio/job.h>
+
+class QString;
+
+/** Namespace for XmlRpc related classes */
+namespace KXmlRpc {
+
+/**
+  @brief
+  Query is a class that represents an individual XML-RPC call.
+
+  This is an internal class and is only used by the KXmlRpc::Client class.
+  @internal
+ */
+class Query : public QObject
+{
+  friend class Result;
+  Q_OBJECT
+
+  public:
+    /**
+      Constructs a query.
+
+      @param id an optional id for the query.
+      @param parent an optional parent for the query.
+     */
+    static Query *create( const QVariant &id = QVariant(), QObject *parent = 0 );
+
+  public Q_SLOTS:
+    /**
+      Calls the specified method on the specified server with
+      the given argument list.
+
+      @param server the server to contact.
+      @param method the method to call.
+      @param args an argument list to pass to said method.
+      @param jobMetaData additional arguments to pass to the KIO::Job.
+     */
+    void call( const QString &server, const QString &method,
+               const QList<QVariant> &args,
+               const QMap<QString, QString> &jobMetaData );
+
+  Q_SIGNALS:
+    /**
+      A signal sent when we receive a result from the server.
+     */
+    void message( const QList<QVariant> &result, const QVariant &id );
+
+    /**
+      A signal sent when we receive an error from the server.
+     */
+    void fault( int, const QString &, const QVariant &id );
+
+    /**
+      A signal sent when a query finishes.
+     */
+    void finished( Query * );
+
+  private:
+    explicit Query( const QVariant &id, QObject *parent = 0 );
+    ~Query();
+
+    class Private;
+    Private *const d;
+
+    Q_PRIVATE_SLOT( d, void slotData( KIO::Job *, const QByteArray & ) )
+    Q_PRIVATE_SLOT( d, void slotResult( KJob * ) )
+};
+
+} // namespace XmlRpc
+
+#endif
+
+
--- /dev/null
+++ tellico-2.3.5+dfsg.1/src/fetch/xmlrpc/client.cpp
@@ -0,0 +1,223 @@
+/*****************************************************************************
+ *   Copyright (C) 2003 - 2004 by Frerich Raabe <ra...@kde.org>               *
+ *                                Tobias Koenig <to...@kde.org>               *
+ *   Copyright (C) 2006 by Narayan Newton <narayannew...@gmail.com>           *
+ *                                                                            *
+ * This program 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. For licensing and distribution        *
+ * details, check the accompanying file 'COPYING.BSD'.                        *
+ *****************************************************************************/
+/**
+  @file
+  This file is part of the API for accessing XML-RPC Servers
+  and defines the Client class.
+
+  @brief
+  Defines the Client class.
+
+  @author Frerich Raabe <ra...@kde.org>
+  @author Tobias Koenig <to...@kde.org>
+  @author Narayan Newton <narayannew...@gmail.com>
+*/
+
+#include "client.h"
+#include "query.h"
+
+#include <kio/job.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kurl.h>
+
+#include <QtCore/QVariant>
+
+using namespace KXmlRpc;
+
+class Client::Private
+{
+  public:
+    Private() : mUserAgent( "KDE XMLRPC resources" ), mDigestAuth( false ){}
+
+    void queryFinished( Query * );
+
+    KUrl mUrl;
+    QString mUserAgent;
+    bool mDigestAuth;
+    QList<Query*> mPendingQueries;
+};
+
+void Client::Private::queryFinished( Query *query )
+{
+  mPendingQueries.removeAll( query );
+  query->deleteLater();
+}
+
+Client::Client( QObject *parent )
+  : QObject( parent ), d( new Private )
+{
+}
+
+Client::Client( const KUrl &url, QObject *parent )
+  : QObject( parent ), d( new Private )
+{
+  d->mUrl = url;
+}
+
+Client::~Client()
+{
+  QList<Query *>::Iterator it;
+  for ( it = d->mPendingQueries.begin(); it != d->mPendingQueries.end(); ++it ) {
+    (*it)->deleteLater();
+  }
+
+  d->mPendingQueries.clear();
+
+  delete d;
+}
+
+void Client::setUrl( const KUrl &url )
+{
+  d->mUrl = url.isValid() ? url : KUrl();
+}
+
+KUrl Client::url() const
+{
+  return d->mUrl;
+}
+
+QString Client::userAgent() const
+{
+  return d->mUserAgent;
+}
+
+void Client::setUserAgent( const QString &userAgent )
+{
+  d->mUserAgent = userAgent;
+}
+
+bool Client::isDigestAuthEnabled() const
+{
+  return d->mDigestAuth;
+}
+
+void Client::setDigestAuthEnabled( bool enabled )
+{
+  d->mDigestAuth = enabled;
+}
+
+void Client::call( const QString &method, const QList<QVariant> &args,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot, const QVariant &id )
+{
+
+  QMap<QString, QString> metaData;
+
+  if ( d->mUrl.isEmpty() ) {
+    kWarning() << "Cannot execute call to" << method << ": empty server URL";
+  }
+
+  //Fill metadata, with userAgent and possible digest auth
+  if ( d->mUserAgent.isEmpty() ) {
+    metaData["UserAgent"] = "KDE-XMLRPC";
+  } else {
+    metaData["UserAgent"] = d->mUserAgent;
+  }
+
+  if ( d->mDigestAuth ) {
+    metaData["WWW-Authenticate:"] = "Digest";
+  }
+
+  Query *query = Query::create( id, this );
+  connect( query, SIGNAL(message(const QList<QVariant> &,const QVariant &)), msgObj, messageSlot );
+  connect( query, SIGNAL(fault(int,const QString &,const QVariant &)), faultObj, faultSlot );
+  connect( query, SIGNAL(finished(Query *)), this, SLOT(queryFinished(Query *)) );
+  d->mPendingQueries.append( query );
+
+  query->call( d->mUrl.url(), method, args, metaData );
+}
+
+void Client::call( const QString &method, const QVariant &arg,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot,
+                   const QVariant &id )
+{
+  QList<QVariant> args;
+  args << arg ;
+  call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Client::call( const QString &method, int arg,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot,
+                   const QVariant &id )
+{
+  QList<QVariant> args;
+  args << QVariant( arg );
+  call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Client::call( const QString &method, bool arg,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot,
+                   const QVariant &id )
+{
+  QList<QVariant> args;
+  args << QVariant( arg );
+  call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Client::call( const QString &method, double arg,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot,
+                   const QVariant &id )
+{
+  QList<QVariant> args;
+  args << QVariant( arg );
+  call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Client::call( const QString &method, const QString &arg,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot,
+                   const QVariant &id )
+{
+  QList<QVariant> args;
+  args << QVariant( arg );
+  call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Client::call( const QString &method, const QByteArray &arg,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot,
+                   const QVariant &id )
+{
+  QList<QVariant> args;
+  args << QVariant( arg );
+  call( method, args, faultObj, faultSlot, msgObj, messageSlot, id );
+}
+
+void Client::call( const QString &method, const QDateTime &arg,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot,
+                   const QVariant &id )
+{
+  QList<QVariant> args;
+  args << QVariant( arg );
+  call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+void Client::call( const QString &method, const QStringList &arg,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot,
+                   const QVariant &id )
+{
+  QList<QVariant> args;
+  for ( int i = 0; i < arg.count(); ++i ) {
+    args << QVariant( arg[ i ] );
+  }
+
+  call( method, args, msgObj, messageSlot, faultObj, faultSlot, id );
+}
+
+#include "client.moc"
+
--- /dev/null
+++ tellico-2.3.5+dfsg.1/src/fetch/xmlrpc/CMakeLists.txt
@@ -0,0 +1,9 @@
+########### next target ###############
+
+SET(xmlrpc_STAT_SRCS
+  query.cpp
+  client.cpp
+   )
+
+KDE4_ADD_LIBRARY(xmlrpc STATIC ${xmlrpc_STAT_SRCS})
+
--- /dev/null
+++ tellico-2.3.5+dfsg.1/src/fetch/xmlrpc/query.cpp
@@ -0,0 +1,454 @@
+/******************************************************************************
+ *   Copyright (C) 2003 - 2004 by Frerich Raabe <ra...@kde.org>               *
+ *                                Tobias Koenig <to...@kde.org>               *
+ *   Copyright (C) 2006 by Narayan Newton <narayannew...@gmail.com>           *
+ *                                                                            *
+ * This program 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. For licensing and distribution        *
+ * details, check the accompanying file 'COPYING.BSD'.                        *
+ *****************************************************************************/
+/**
+  @file
+
+  This file is part of KXmlRpc and defines our internal classes.
+
+  @author Frerich Raabe <ra...@kde.org>
+  @author Tobias Koenig <to...@kde.org>
+  @author Narayan Newton <narayannew...@gmail.com>
+*/
+
+#include "query.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <QtCore/QDateTime>
+#include <QtCore/QVariant>
+#include <QtXml/QDomDocument>
+
+
+using namespace KXmlRpc;
+
+/**
+  @file
+
+  Implementation of Query
+**/
+
+namespace KXmlRpc {
+
+/**
+  @brief
+  Result is an internal class that represents a response
+  from a XML-RPC server.
+
+  This is an internal class and is only used by Query.
+  @internal
+ */
+class Result
+{
+  friend class Query;
+  friend class Query::Private;
+
+  public:
+    /**
+      Constructs a result.
+     */
+    Result();
+
+    /**
+      Destroys a result.
+     */
+    ~Result();
+
+    /**
+      Returns true if the method call succeeded, false
+      if there was an XML-RPC fault.
+
+      @see errorCode(), errorString()
+     */
+    bool success() const;
+
+    /**
+      Returns the error code of the fault.
+
+      @see success(), errorString()
+     */
+    int errorCode() const;
+
+    /**
+      Returns the error string that describes the fault.
+
+      @see success, errorCode()
+     */
+    QString errorString() const;
+
+    /**
+      Returns the data sent to us from the server.
+     */
+    QList<QVariant> data() const;
+
+  private:
+    bool mSuccess;
+    int mErrorCode;
+    QString mErrorString;
+    QList<QVariant> mData;
+};
+
+} // namespace KXmlRpcClient
+
+KXmlRpc::Result::Result()
+{
+}
+
+KXmlRpc::Result::~Result()
+{
+}
+
+bool KXmlRpc::Result::success() const
+{
+  return mSuccess;
+}
+
+int KXmlRpc::Result::errorCode() const
+{
+  return mErrorCode;
+}
+
+QString KXmlRpc::Result::errorString() const
+{
+  return mErrorString;
+}
+
+QList<QVariant> KXmlRpc::Result::data() const
+{
+  return mData;
+}
+
+class Query::Private
+{
+  public:
+    Private( Query *parent )
+      : mParent( parent )
+    {
+    }
+
+    bool isMessageResponse( const QDomDocument &doc ) const;
+    bool isFaultResponse( const QDomDocument &doc ) const;
+
+    Result parseMessageResponse( const QDomDocument &doc ) const;
+    Result parseFaultResponse( const QDomDocument &doc ) const;
+
+    QString markupCall( const QString &method, const QList<QVariant> &args ) const;
+    QString marshal( const QVariant &value ) const;
+    QVariant demarshal( const QDomElement &element ) const;
+
+    void slotData( KIO::Job *job, const QByteArray &data );
+    void slotResult( KJob *job );
+
+    Query *mParent;
+    QByteArray mBuffer;
+    QVariant mId;
+    QList<KJob*> mPendingJobs;
+};
+
+bool Query::Private::isMessageResponse( const QDomDocument &doc ) const
+{
+  return doc.documentElement().firstChild().toElement().tagName().toLower()
+      == "params";
+}
+
+bool Query::Private::isFaultResponse( const QDomDocument &doc ) const
+{
+  return doc.documentElement().firstChild().toElement().tagName().toLower()
+      == "fault";
+}
+
+Result Query::Private::parseMessageResponse( const QDomDocument &doc ) const
+{
+  Result response;
+  response.mSuccess = true;
+
+  QDomNode paramNode = doc.documentElement().firstChild().firstChild();
+  while ( !paramNode.isNull() ) {
+    response.mData << demarshal( paramNode.firstChild().toElement() );
+    paramNode = paramNode.nextSibling();
+  }
+
+  return response;
+}
+
+Result Query::Private::parseFaultResponse( const QDomDocument &doc ) const
+{
+  Result response;
+  response.mSuccess = false;
+
+  QDomNode errorNode = doc.documentElement().firstChild().firstChild();
+  const QVariant errorVariant = demarshal( errorNode.toElement() );
+  response.mErrorCode = errorVariant.toMap() [ "faultCode" ].toInt();
+  response.mErrorString = errorVariant.toMap() [ "faultString" ].toString();
+
+  return response;
+}
+
+QString Query::Private::markupCall( const QString &cmd,
+                                    const QList<QVariant> &args ) const
+{
+  QString markup = "<?xml version=\"1.0\" ?>\r\n<methodCall>\r\n";
+
+  markup += "<methodName>" + cmd + "</methodName>\r\n";
+
+  if ( !args.isEmpty() ) {
+
+    markup += "<params>\r\n";
+    QList<QVariant>::ConstIterator it = args.begin();
+    QList<QVariant>::ConstIterator end = args.end();
+    for ( ; it != end; ++it ) {
+      markup += "<param>\r\n" + marshal( *it ) + "</param>\r\n";
+    }
+    markup += "</params>\r\n";
+  }
+
+  markup += "</methodCall>\r\n";
+
+  return markup;
+}
+
+QString Query::Private::marshal( const QVariant &arg ) const
+{
+  switch ( arg.type() ) {
+
+    case QVariant::String:
+      return "<value><string><![CDATA[" + arg.toString() + "]]></string></value>\r\n";
+    case QVariant::StringList:
+      {
+        QStringList data = arg.toStringList();
+        QStringListIterator dataIterator(data);
+        QString markup;
+        markup += "<value><array><data>";
+        while ( dataIterator.hasNext() ) {
+          markup += "<value><string><![CDATA[" + dataIterator.next() + "]]></string></value>\r\n";
+        }
+        markup += "</data></array></value>";
+        return markup;
+      }
+    case QVariant::Int:
+      return "<value><int>" + QString::number( arg.toInt() ) + "</int></value>\r\n";
+    case QVariant::Double:
+      return "<value><double>" + QString::number( arg.toDouble() ) + "</double></value>\r\n";
+    case QVariant::Bool:
+      {
+        QString markup = "<value><boolean>";
+        markup += arg.toBool() ? "1" : "0";
+        markup += "</boolean></value>\r\n";
+        return markup;
+      }
+    case QVariant::ByteArray:
+      return "<value><base64>" + arg.toByteArray().toBase64() + "</base64></value>\r\n";
+    case QVariant::DateTime:
+      {
+        return "<value><dateTime.iso8601>" +
+          arg.toDateTime().toString( Qt::ISODate ) +
+          "</dateTime.iso8601></value>\r\n";
+      }
+    case QVariant::List:
+      {
+        QString markup = "<value><array><data>\r\n";
+        const QList<QVariant> args = arg.toList();
+        QList<QVariant>::ConstIterator it = args.begin();
+        QList<QVariant>::ConstIterator end = args.end();
+        for ( ; it != end; ++it ) {
+          markup += marshal( *it );
+        }
+        markup += "</data></array></value>\r\n";
+        return markup;
+      }
+    case QVariant::Map:
+      {
+        QString markup = "<value><struct>\r\n";
+        QMap<QString, QVariant> map = arg.toMap();
+        QMap<QString, QVariant>::ConstIterator it = map.constBegin();
+        QMap<QString, QVariant>::ConstIterator end = map.constEnd();
+        for ( ; it != end; ++it ) {
+          markup += "<member>\r\n";
+          markup += "<name>" + it.key() + "</name>\r\n";
+          markup += marshal( it.value() );
+          markup += "</member>\r\n";
+        }
+        markup += "</struct></value>\r\n";
+        return markup;
+      }
+    default:
+      kWarning() << "Failed to marshal unknown variant type:" << arg.type();
+  };
+
+  return QString();
+}
+
+QVariant Query::Private::demarshal( const QDomElement &element ) const
+{
+  Q_ASSERT( element.tagName().toLower() == "value" );
+
+  const QDomElement typeElement = element.firstChild().toElement();
+  const QString typeName = typeElement.tagName().toLower();
+
+  if ( typeName == "string" ) {
+    return QVariant( typeElement.text() );
+  } else if ( typeName == "i4" || typeName == "int" ) {
+    return QVariant( typeElement.text().toInt() );
+  } else if ( typeName == "double" ) {
+    return QVariant( typeElement.text().toDouble() );
+  } else if ( typeName == "boolean" ) {
+
+    if ( typeElement.text().toLower() == "true" || typeElement.text() == "1" ) {
+      return QVariant( true );
+    } else {
+      return QVariant( false );
+    }
+  } else if ( typeName == "base64" ) {
+    return QVariant( QByteArray::fromBase64( typeElement.text().toLatin1() ) );
+  } else if ( typeName == "datetime" || typeName == "datetime.iso8601" ) {
+    QDateTime date;
+    QString dateText = typeElement.text();
+    // Test for broken use of Basic ISO8601 date and extended ISO8601 time
+    if ( 17 <= dateText.length() && dateText.length() <= 18 &&
+         dateText.at( 4 ) != '-' && dateText.at( 11 ) == ':' ) {
+        if ( dateText.endsWith( 'Z' ) ) {
+          date = QDateTime::fromString( dateText, "yyyyMMddTHH:mm:ssZ" );
+        } else {
+          date = QDateTime::fromString( dateText, "yyyyMMddTHH:mm:ss" );
+        }
+    } else {
+      date = QDateTime::fromString( dateText, Qt::ISODate );
+    }
+    return QVariant( date );
+  } else if ( typeName == "array" ) {
+    QList<QVariant> values;
+    QDomNode valueNode = typeElement.firstChild().firstChild();
+    while ( !valueNode.isNull() ) {
+      values << demarshal( valueNode.toElement() );
+      valueNode = valueNode.nextSibling();
+    }
+    return QVariant( values );
+  } else if ( typeName == "struct" ) {
+
+    QMap<QString, QVariant> map;
+    QDomNode memberNode = typeElement.firstChild();
+    while ( !memberNode.isNull() ) {
+      const QString key = memberNode.toElement().elementsByTagName(
+                              "name" ).item( 0 ).toElement().text();
+      const QVariant data = demarshal( memberNode.toElement().elementsByTagName(
+                                       "value" ).item( 0 ).toElement() );
+      map[ key ] = data;
+      memberNode = memberNode.nextSibling();
+    }
+    return QVariant( map );
+  } else {
+    kWarning() << "Cannot demarshal unknown type" << typeName;
+  }
+  return QVariant();
+}
+
+void Query::Private::slotData( KIO::Job *, const QByteArray &data )
+{
+  unsigned int oldSize = mBuffer.size();
+  mBuffer.resize( oldSize + data.size() );
+  memcpy( mBuffer.data() + oldSize, data.data(), data.size() );
+}
+
+void Query::Private::slotResult( KJob *job )
+{
+  mPendingJobs.removeAll( job );
+
+  if ( job->error() != 0 ) {
+    emit mParent->fault( job->error(), job->errorString(), mId );
+    emit mParent->finished( mParent );
+    return;
+  }
+
+//  const QString data = QString::fromUtf8( mBuffer.data(), mBuffer.size() );
+
+  QDomDocument doc;
+  QString errMsg;
+  int errLine, errCol;
+  if ( !doc.setContent( mBuffer, false, &errMsg, &errLine, &errCol ) ) {
+    emit mParent->fault( -1, i18n( "Received invalid XML markup: %1 at %2:%3",
+                                   errMsg, errLine, errCol ), mId );
+    emit mParent->finished( mParent );
+    return;
+  }
+
+  mBuffer.truncate( 0 );
+
+  if ( isMessageResponse( doc ) ) {
+    emit mParent->message( parseMessageResponse( doc ).data(), mId );
+  } else if ( isFaultResponse( doc ) ) {
+    emit mParent->fault( parseFaultResponse( doc ).errorCode(),
+                         parseFaultResponse( doc ).errorString(), mId );
+  } else {
+    emit mParent->fault( 1, i18n( "Unknown type of XML markup received" ),
+                         mId );
+  }
+
+  emit mParent->finished( mParent );
+}
+
+Query *Query::create( const QVariant &id, QObject *parent )
+{
+  return new Query( id, parent );
+}
+
+void Query::call( const QString &server,
+                  const QString &method,
+                  const QList<QVariant> &args,
+                  const QMap<QString, QString> &jobMetaData )
+{
+
+  const QString xmlMarkup = d->markupCall( method, args );
+
+  QMap<QString, QString>::const_iterator mapIter;
+  QByteArray postData;
+  QDataStream stream( &postData, QIODevice::WriteOnly );
+  stream.writeRawData( xmlMarkup.toUtf8(), xmlMarkup.toUtf8().length() );
+
+  KIO::TransferJob *job = KIO::http_post( KUrl( server ), postData, KIO::HideProgressInfo );
+
+  if ( !job ) {
+    kWarning() << "Unable to create KIO job for" << server;
+    return;
+  }
+
+  job->addMetaData( "content-type", "Content-Type: text/xml; charset=utf-8" );
+  job->addMetaData( "ConnectTimeout", "50" );
+
+  for ( mapIter = jobMetaData.begin(); mapIter != jobMetaData.end(); ++mapIter ) {
+    job->addMetaData( mapIter.key(), mapIter.value() );
+  }
+
+  connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
+           this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
+  connect( job, SIGNAL( result( KJob * ) ),
+           this, SLOT( slotResult( KJob * ) ) );
+
+  d->mPendingJobs.append( job );
+}
+
+Query::Query( const QVariant &id, QObject *parent )
+  : QObject( parent ), d( new Private( this ) )
+{
+  d->mId = id;
+}
+
+Query::~Query()
+{
+  QList<KJob*>::Iterator it;
+  for ( it = d->mPendingJobs.begin(); it != d->mPendingJobs.end(); ++it ) {
+    (*it)->kill();
+  }
+  delete d;
+}
+
+#include "query.moc"
+
+
--- /dev/null
+++ tellico-2.3.5+dfsg.1/src/fetch/xmlrpc/client.h
@@ -0,0 +1,323 @@
+/******************************************************************************
+ *   Copyright (C) 2003 - 2004 by Frerich Raabe <ra...@kde.org>               *
+ *                                Tobias Koenig <to...@kde.org>               *
+ *   Copyright (C) 2006 by Narayan Newton <narayannew...@gmail.com>           *
+ *                                                                            *
+ * This program 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. For licensing and distribution        *
+ * details, check the accompanying file 'COPYING.BSD'.                        *
+ *****************************************************************************/
+/**
+  @file
+  This file is part of the API for accessing XML-RPC Servers
+  and defines the Client class.
+
+  @brief
+  Defines the Client class.
+
+  @author Frerich Raabe <ra...@kde.org>
+  @author Tobias Koenig <to...@kde.org>
+  @author Narayan Newton <narayannew...@gmail.com>
+*/
+
+#ifndef KXML_RPC_CLIENT_H
+#define KXML_RPC_CLIENT_H
+
+#undef QT_NO_CAST_FROM_ASCII
+
+#include <kurl.h>
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QVariant>
+
+/** Names for XmlRpc related classes */
+namespace KXmlRpc {
+
+/**
+  @brief
+  A class that represents a connection to a XML-RPC server.
+  This is the main interface to the XML-RPC client library.
+
+  @code
+    KXmlRpc::Client *c = new Client(KUrl( "http://localhost"; ), this);
+    c->setUserAgent( "Test/1.0" );
+    c->call( "xmlrpc.command1", "Hi!",
+       this, SLOT( gotData( const QList<QVariant>&, const QVariant ) ),
+       this, SLOT( gotError( const QString&, const QVariant& ) ) );
+  @endcode
+
+  @author Narayan Newton <narayannew...@gmail.com>
+ */
+class Client : public QObject
+{
+  Q_OBJECT
+
+  public:
+    /**
+      Constructs a XML-RPC Client.
+
+      @param parent the parent of this object, defaults to NULL.
+     */
+    explicit Client( QObject *parent = 0 );
+
+    /**
+      Constructs a XML-RPC Client, which will connect to @p url.
+
+      @param url the url of the xml-rpc server.
+      @param parent the parent of this object, defaults to NULL.
+     */
+    explicit Client( const KUrl &url, QObject *parent = 0 );
+
+    /**
+      Destroys the XML-RPC Client.
+     */
+    ~Client();
+
+    /**
+      Returns the current url the XML-RPC Client will connect to.
+
+      @see setUrl()
+     */
+    KUrl url() const;
+
+    /**
+      Sets the url the Client will connect to.
+
+      @param url the url for the xml-rpc server we will be connecting to.
+
+      @see url()
+     */
+    void setUrl( const KUrl &url );
+
+    /**
+      Returns the user agent string currently used by the Client.
+
+      @see setUserAgent()
+     */
+    QString userAgent() const;
+
+    /**
+      Sets the userAgent string the Client will use to identify itself.
+
+      @param userAgent the user agent string to use.
+
+      @see userAgent()
+     */
+    void setUserAgent( const QString &userAgent );
+
+    /**
+      Returns true if HTTP-Digest authentication is enabled, false
+      if not.
+
+      @see setDigestAuthEnabled()
+     */
+    bool isDigestAuthEnabled() const;
+
+    /**
+      Enables/disables HTTP-Digest authentication
+
+      @see isDigestAuthEnabled()
+     */
+
+    void setDigestAuthEnabled( bool enabled );
+
+  public Q_SLOTS:
+    /**
+      Calls the given method on a XML-RPC server, with the given
+      argument list.
+
+      @param method the method on the server we are going to be calling
+      @param args the argument list to pass to the server
+      @param msgObj the object containing the data slot
+      @param messageSlot the data slot itself
+      @param faultObj the object containing the error slot
+      @param faultSlot the error slot itself
+      @param id the id for our #Client object, defaults to empty
+     */
+    void call( const QString &method, const QList<QVariant> &args,
+               QObject *msgObj, const char *messageSlot,
+               QObject *faultObj, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+    /**
+      Calls the given method on a XML-RPC server, with the given
+      argument.
+
+      @param method the method on the server we are going to be calling
+      @param arg the argument to pass to the server
+      @param msgObj the object containing the data slot
+      @param messageSlot the data slot itself
+      @param faultObj the object containing the error slot
+      @param faultSlot the error slot itself
+      @param id the id for our Client object, defaults to empty
+     */
+    void call( const QString &method, const QVariant &arg,
+               QObject *msgObj, const char *messageSlot,
+               QObject *faultObj, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+    /**
+      Calls the given method on a XML-RPC server, with the given
+      int as the argument.
+
+      @param method the method on the server we are going to be calling
+      @param arg the int to pass to the server
+      @param msgObj the object containing the data slot
+      @param messageSlot the data slot itself
+      @param faultObj the object containing the error slot
+      @param faultSlot the error slot itself
+      @param id the id for our Client object, defaults to empty
+     */
+    void call( const QString &method, int arg,
+               QObject *msgObj, const char *messageSlot,
+               QObject *faultObj, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+    /**
+      Calls the given method on a XML-RPC server, with the given
+      bool as the argument.
+
+      @param method the method on the server we are going to be calling
+      @param arg the bool to pass to the server
+      @param msgObj the object containing the data slot
+      @param messageSlot the data slot itself
+      @param faultObj the object containing the error slot
+      @param faultSlot the error slot itself
+      @param id the id for our Client object, defaults to empty
+     */
+    void call( const QString &method, bool arg,
+               QObject *msgObj, const char *messageSlot,
+               QObject *faultObj, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+    /**
+      Calls the given method on a XML-RPC server, with the given
+      double as the argument.
+
+      @param method the method on the server we are going to be calling
+      @param arg the double to pass to the server
+      @param msgObj the object containing the data slot
+      @param messageSlot the data slot itself
+      @param faultObj the object containing the error slot
+      @param faultSlot the error slot itself
+      @param id the id for our Client object, defaults to empty
+     */
+    void call( const QString &method, double arg,
+               QObject *msgObj, const char *messageSlot,
+               QObject *faultObj, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+    /**
+      Calls the given method on a XML-RPC server, with the given
+      string as the argument.
+
+      @param method the method on the server we are going to be calling
+      @param arg the string to pass to the server
+      @param msgObj the object containing the data slot
+      @param messageSlot the data slot itself
+      @param faultObj the object containing the error slot
+      @param faultSlot the error slot itself
+      @param id the id for our Client object, defaults to empty
+     */
+    void call( const QString &method, const QString &arg,
+               QObject *msgObj, const char *messageSlot,
+               QObject *faultObj, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+    /**
+      Calls the given method on a XML-RPC server, with the given
+      byte array as the argument.
+
+      @param method the method on the server we are going to be calling
+      @param arg the array to pass to the server
+      @param msgObj the object containing the data slot
+      @param messageSlot the data slot itself
+      @param faultObj the object containing the error slot
+      @param faultSlot the error slot itself
+      @param id the id for our Client object, defaults to empty
+     */
+    void call( const QString &method, const QByteArray &arg,
+               QObject *msgObj, const char *messageSlot,
+               QObject *faultObj, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+    /**
+      Calls the given method on a XML-RPC server, with the given
+      date as the argument
+
+      @param method the method on the server we are going to be calling
+      @param arg the date and/or time to pass to the server
+      @param msgObj the object containing the data slot
+      @param messageSlot the data slot itself
+      @param faultObj the object containing the error slot
+      @param faultSlot the error slot itself
+      @param id the id for our Client object, defaults to empty
+     */
+    void call( const QString &method, const QDateTime &arg,
+               QObject *msgObj, const char *messageSlot,
+               QObject *faultObj, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+    /**
+      Calls the given method on a XML-RPC server, with the given
+      string list as the argument
+
+      @param method the method on the server we are going to be calling
+      @param arg the list of strings to pass to the server
+      @param msgObj the object containing the data slot
+      @param messageSlot the data slot itself
+      @param faultObj the object containing the error slot
+      @param faultSlot the error slot itself
+      @param id the id for our Client object, defaults to empty
+     */
+    void call( const QString &method, const QStringList &arg,
+               QObject *msgObj, const char *messageSlot,
+               QObject *faultObj, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+  private:
+    class Private;
+    Private *const d;
+
+    template <typename T>
+    void call( const QString &method, const QList<T> &arg,
+               QObject *obj1, const char *messageSlot,
+               QObject *obj2, const char *faultSlot,
+               const QVariant &id = QVariant() );
+
+    Q_PRIVATE_SLOT( d, void queryFinished( Query * ) )
+};
+
+/**
+  Calls the given method on a XML-RPC server with the given
+  list of type T arguments.
+
+  @param method the method on the server we are going to be calling
+  @param arg the list of type T to pass to the server
+  @param msgObj the object containing the data slot
+  @param messageSlot the data slot itself
+  @param faultObj the object containing the error slot
+  @param faultSlot the error slot itself
+  @param id the id for our Client object, defaults to empty
+*/
+template <typename T>
+void Client::call( const QString &method, const QList<T> &arg,
+                   QObject *msgObj, const char *messageSlot,
+                   QObject *faultObj, const char *faultSlot,
+                   const QVariant &id )
+{
+  QList<QVariant> args;
+
+  for ( int i = 0; i < arg.count(); ++i ) {
+    args << QVariant( arg[ i ] );
+  }
+
+  return call( method, args, faultObj, faultSlot, msgObj, messageSlot, id );
+}
+
+}
+
+#endif
+

Reply via email to