00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "blobiohandler.h"
00025
00026 #include <QBuffer>
00027 #include <QDebug>
00028
00029 #include "SignOn/signonplugincommon.h"
00030
00031 #define SIGNON_IPC_BUFFER_PAGE_SIZE 16384
00032
00033 using namespace SignOn;
00034
00035 BlobIOHandler::BlobIOHandler(QIODevice *readChannel,
00036 QIODevice *writeChannel,
00037 QObject *parent):
00038 QObject(parent),
00039 m_readChannel(readChannel),
00040 m_writeChannel(writeChannel),
00041 m_readNotifier(0),
00042 m_blobSize(-1)
00043 {
00044 }
00045
00046 void BlobIOHandler::setReadChannelSocketNotifier(QSocketNotifier *notifier)
00047 {
00048 if (notifier == 0)
00049 return;
00050
00051 m_readNotifier = notifier;
00052 }
00053
00054 bool BlobIOHandler::sendData(const QVariantMap &map)
00055 {
00056 if (m_writeChannel == 0) {
00057 TRACE() << "NULL write channel.";
00058 return false;
00059 }
00060
00061 QDataStream stream(m_writeChannel);
00062 QByteArray ba = variantMapToByteArray(map);
00063 stream << ba.size();
00064
00065 QVector<QByteArray> pages = pageByteArray(ba);
00066 for (int i = 0; i < pages.count(); ++i)
00067 stream << pages[i];
00068
00069 return true;
00070 }
00071
00072 void BlobIOHandler::setReadNotificationEnabled(bool enabled)
00073 {
00074 if (enabled) {
00075 if (m_readNotifier != 0) {
00076 m_readNotifier->setEnabled(true);
00077 connect(m_readNotifier, SIGNAL(activated(int)),
00078 this, SLOT(readBlob()));
00079 } else {
00080 connect(m_readChannel, SIGNAL(readyRead()),
00081 this, SLOT(readBlob()));
00082 }
00083 } else {
00084 if (m_readNotifier != 0) {
00085 disconnect(m_readNotifier, SIGNAL(activated(int)),
00086 this, SLOT(readBlob()));
00087 m_readNotifier->setEnabled(false);
00088 } else {
00089 disconnect(m_readChannel, SIGNAL(readyRead()),
00090 this, SLOT(readBlob()));
00091 }
00092 }
00093 }
00094
00095 void BlobIOHandler::receiveData(int expectedDataSize)
00096 {
00097 m_blobBuffer.clear();
00098 m_blobSize = expectedDataSize;
00099
00100
00101
00102 if (m_blobSize > SIGNON_IPC_BUFFER_PAGE_SIZE)
00103 setReadNotificationEnabled(true);
00104
00105 readBlob();
00106 }
00107
00108 void BlobIOHandler::readBlob()
00109 {
00110 QDataStream in(m_readChannel);
00111
00112 QByteArray fractionBa;
00113 in >> fractionBa;
00114 m_blobBuffer.append(fractionBa);
00115
00116
00117 if ((fractionBa.size() == 0) && (m_blobBuffer.size() < m_blobSize)) {
00118 setReadNotificationEnabled(false);
00119 emit error();
00120 return;
00121 }
00122
00123 if (m_blobBuffer.size() == m_blobSize) {
00124 QVariantMap sessionDataMap;
00125 sessionDataMap = byteArrayToVariantMap(m_blobBuffer);
00126
00127 if (m_blobSize > SIGNON_IPC_BUFFER_PAGE_SIZE)
00128 setReadNotificationEnabled(false);
00129
00130 emit dataReceived(sessionDataMap);
00131 }
00132 }
00133
00134 static QVariantMap filterOutComplexTypes(const QVariantMap &map)
00135 {
00136 QVariantMap filteredMap;
00137 QVariantMap::const_iterator i;
00138 for (i = map.constBegin(); i != map.constEnd(); i++) {
00139
00140
00141
00142
00143 if (qstrcmp(i.value().typeName(), "QDBusArgument") == 0) {
00144 BLAME() << "Found QDBusArgument in map; skipping.";
00145 continue;
00146 }
00147 filteredMap.insert(i.key(), i.value());
00148 }
00149 return filteredMap;
00150 }
00151
00152 QByteArray BlobIOHandler::variantMapToByteArray(const QVariantMap &map)
00153 {
00154 QBuffer buffer;
00155 if (!buffer.open(QIODevice::WriteOnly))
00156 BLAME() << "Buffer opening failed.";
00157
00158 QDataStream stream(&buffer);
00159 stream << filterOutComplexTypes(map);
00160 buffer.close();
00161
00162 return buffer.data();
00163 }
00164
00165 QVariantMap BlobIOHandler::byteArrayToVariantMap(const QByteArray &array)
00166 {
00167 QByteArray nonConst = array;
00168 QBuffer buffer(&nonConst);
00169 if (!buffer.open(QIODevice::ReadOnly))
00170 BLAME() << "Buffer opening failed.";
00171
00172 buffer.reset();
00173 QDataStream stream(&buffer);
00174 QVariantMap map;
00175 stream >> map;
00176 buffer.close();
00177
00178 return map;
00179 }
00180
00181 QVector<QByteArray> BlobIOHandler::pageByteArray(const QByteArray &array)
00182 {
00183 QVector<QByteArray> dataPages;
00184 QByteArray ba = array;
00185 QBuffer pagingBuffer(&ba);
00186
00187 if (!pagingBuffer.open(QIODevice::ReadOnly))
00188 BLAME() << "Error while paging BLOB. Buffer opening failed.";
00189
00190 while (!pagingBuffer.atEnd()) {
00191 QByteArray page = pagingBuffer.read(SIGNON_IPC_BUFFER_PAGE_SIZE);
00192 dataPages.append(page);
00193 }
00194 pagingBuffer.close();
00195
00196 return dataPages;
00197 }