Skip to content

Commit

Permalink
Add in ability to add a custom header for postAuth and downloadAuth
Browse files Browse the repository at this point in the history
Right now, this is only required by postAuth, to add the Accept-Encoding: gzip
for DataDirect pulls.

Also added in code based on the public-domain zlib example that will actually
gunzip the data in Qt via zlib (which we already include anyways).
  • Loading branch information
Beirdo committed Feb 9, 2012
1 parent 8928e97 commit de3ade3
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 39 deletions.
56 changes: 38 additions & 18 deletions mythtv/libs/libmythbase/mythdownloadmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ class MythDownloadInfo
MythDownloadInfo() :
m_request(NULL), m_reply(NULL), m_data(NULL),
m_caller(NULL), m_requestType(kRequestGet),
m_reload(false), m_preferCache(false),m_syncMode(false),
m_processReply(true), m_done(false), m_bytesReceived(0),
m_reload(false), m_preferCache(false), m_syncMode(false),
m_processReply(true), m_done(false), m_bytesReceived(0),
m_bytesTotal(0), m_lastStat(QDateTime::currentDateTime()),
m_authCallback(NULL), m_authArg(NULL),
m_header(NULL), m_headerVal(NULL),
m_errorCode(QNetworkReply::NoError)
{
qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
Expand Down Expand Up @@ -83,6 +84,8 @@ class MythDownloadInfo
QDateTime m_lastStat;
void (*m_authCallback)(QNetworkReply*, QAuthenticator*, void*);
void *m_authArg;
const QByteArray *m_header;
const QByteArray *m_headerVal;

QNetworkReply::NetworkError m_errorCode;
};
Expand Down Expand Up @@ -336,10 +339,12 @@ void MythDownloadManager::queueItem(const QString &url, QNetworkRequest *req,
bool MythDownloadManager::processItem(const QString &url, QNetworkRequest *req,
const QString &dest, QByteArray *data,
const MRequestType reqType,
const bool reload,
void (*authCallback)(QNetworkReply*,
QAuthenticator*,
void*),
void *authArg, const bool reload)
void *authArg, const QByteArray *header,
const QByteArray *headerVal)
{
MythDownloadInfo *dlInfo = new MythDownloadInfo;

Expand All @@ -351,7 +356,9 @@ bool MythDownloadManager::processItem(const QString &url, QNetworkRequest *req,
dlInfo->m_reload = reload;
dlInfo->m_syncMode = true;
dlInfo->m_authCallback = authCallback;
dlInfo->m_authArg = authArg;
dlInfo->m_authArg = authArg;
dlInfo->m_header = header;
dlInfo->m_headerVal = headerVal;

return downloadNow(dlInfo);
}
Expand Down Expand Up @@ -418,30 +425,36 @@ void MythDownloadManager::queueDownload(QNetworkRequest *req,
bool MythDownloadManager::download(const QString &url, const QString &dest,
const bool reload)
{
return processItem(url, NULL, dest, NULL, kRequestGet, NULL, NULL, reload);
return processItem(url, NULL, dest, NULL, kRequestGet, reload);
}

/** \fn MythDownloadManager::downloadAuth(const QString &url,
* const QString &dest,
* const bool reload,
* void (*authCallback)(QNetworkReply*,
* QAuthenticator*,
* void*),
* void *authArg,
* const bool reload)
* const QByteArray *header,
* const QByteArray *headerVal)
* \brief Downloads a URL to a file in blocking mode.
* \param url URI to download.
* \param dest Destination filename.
* \param reload Whether to force reloading of the URL or not
* \param authCallback Callback function for use with authentication
* \param authArg Opaque argument for callback function
* \param reload Whether to force reloading of the URL or not
* \param header Optional HTTP header to add to the request
* \param headerVal Value for the optional HTTP header to add to the request
* \return true if download was successful, false otherwise.
*/
bool MythDownloadManager::downloadAuth(const QString &url, const QString &dest,
const bool reload,
void (*authCallback)(QNetworkReply*, QAuthenticator*, void*),
void *authArg, const bool reload)
void *authArg, const QByteArray *header,
const QByteArray *headerVal)
{
return processItem(url, NULL, dest, NULL, kRequestGet, authCallback,
authArg, reload);
return processItem(url, NULL, dest, NULL, kRequestGet, reload, authCallback,
authArg, header, headerVal);
}

/** \fn MythDownloadManager::download(const QString &url,
Expand All @@ -456,8 +469,7 @@ bool MythDownloadManager::downloadAuth(const QString &url, const QString &dest,
bool MythDownloadManager::download(const QString &url, QByteArray *data,
const bool reload)
{
return processItem(url, NULL, QString(), data, kRequestGet, NULL, NULL,
reload);
return processItem(url, NULL, QString(), data, kRequestGet, reload);
}

/** \fn MythDownloadManager::download(const QString &url,
Expand Down Expand Up @@ -556,20 +568,22 @@ void MythDownloadManager::queuePost(QNetworkRequest *req,

/** \fn MythDownloadManager::postAuth(const QString &url, QByteArray *data,
* void (*authCallback)(QNetworkReply*, QAuthenticator*, void*),
* void *authArg)
* void *authArg, const QByteArray *header,
* const QByteArray *headerVal)
* \brief Posts data to a url via the QNetworkAccessManager
* \param url URL to post to
* data Location holding post and response data
* dest Destination filename
* authCallback Callback function for authentication
* authArg Opaque argument for callback function
* \param header Optional HTTP header to add to the request
* \param headerVal Value for the optional HTTP header to add to the request
* \return true if post was successful, false otherwise.
*/
bool MythDownloadManager::postAuth(const QString &url, QByteArray *data,
const QString &dest,
void (*authCallback)(QNetworkReply*,
QAuthenticator*, void*),
void *authArg)
void *authArg, const QByteArray *header,
const QByteArray *headerVal)
{
LOG(VB_FILE, LOG_DEBUG, LOC + QString("postAuth('%1', '%2')")
.arg(url).arg((long long)data));
Expand All @@ -580,8 +594,8 @@ bool MythDownloadManager::postAuth(const QString &url, QByteArray *data,
return false;
}

return processItem(url, NULL, dest, data, kRequestPost, authCallback,
authArg);
return processItem(url, NULL, NULL, data, kRequestPost, false, authCallback,
authArg, header, headerVal);
}

/** \fn MythDownloadManager::post(const QString &url, QByteArray *data)
Expand Down Expand Up @@ -703,6 +717,12 @@ void MythDownloadManager::downloadQNetworkRequest(MythDownloadInfo *dlInfo)
request.setRawHeader("User-Agent",
"MythDownloadManager v" MYTH_BINARY_VERSION);

if (dlInfo->m_header && dlInfo->m_headerVal &&
!dlInfo->m_header->isEmpty() && !dlInfo->m_headerVal->isEmpty())
{
request.setRawHeader(*(dlInfo->m_header), *(dlInfo->m_headerVal));
}

switch (dlInfo->m_requestType)
{
case kRequestPost :
Expand Down
15 changes: 10 additions & 5 deletions mythtv/libs/libmythbase/mythdownloadmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ class MBASE_PUBLIC MythDownloadManager : public QObject, public MThread
bool download(const QString &url, const QString &dest,
const bool reload = false);
bool downloadAuth(const QString &url, const QString &dest,
const bool reload = false,
void (*authCallback)(QNetworkReply*, QAuthenticator*,
void*),
void *authArg, const bool reload);
void*) = NULL,
void *authArg = NULL, const QByteArray *header = NULL,
const QByteArray *headerVal = NULL);
bool download(const QString &url, QByteArray *data,
const bool reload = false);
QNetworkReply *download(const QString &url, const bool reload = false);
Expand All @@ -56,9 +58,10 @@ class MBASE_PUBLIC MythDownloadManager : public QObject, public MThread
void queuePost(const QString &url, QByteArray *data, QObject *caller);
void queuePost(QNetworkRequest *req, QByteArray *data, QObject *caller);
bool post(const QString &url, QByteArray *data);
bool postAuth(const QString &url, QByteArray *data, const QString &dest,
bool postAuth(const QString &url, QByteArray *data,
void (*authCallback)(QNetworkReply*, QAuthenticator*, void*),
void *authArg);
void *authArg, const QByteArray *header = NULL,
const QByteArray *headerVal = NULL);
bool post(QNetworkRequest *req, QByteArray *data);

// Cancel a download
Expand Down Expand Up @@ -98,9 +101,11 @@ class MBASE_PUBLIC MythDownloadManager : public QObject, public MThread
bool processItem(const QString &url, QNetworkRequest *req,
const QString &dest, QByteArray *data,
const MRequestType reqType = kRequestGet,
const bool reload = false,
void (*authCallback)(QNetworkReply*, QAuthenticator*,
void*) = NULL,
void *authArg = NULL, const bool reload = false);
void *authArg = NULL, const QByteArray *header = NULL,
const QByteArray *headerVal = NULL);

void downloadRemoteFile(MythDownloadInfo *dlInfo);
void downloadQNetworkRequest(MythDownloadInfo *dlInfo);
Expand Down
77 changes: 61 additions & 16 deletions mythtv/libs/libmythtv/datadirect.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <unistd.h>
#include <zlib.h>

// Qt headers
#include <QDir>
Expand Down Expand Up @@ -49,6 +50,7 @@ static uint update_channel_basic(uint sourceid, bool insert,
QString chan_major, QString chan_minor);
void authenticationCallback(QNetworkReply *reply, QAuthenticator *auth,
void *arg);
QByteArray gUncompress(const QByteArray &data);

DataDirectStation::DataDirectStation(void) :
stationid(""), callsign(""),
Expand Down Expand Up @@ -1012,31 +1014,25 @@ bool DataDirectProcessor::DDPost(QString ddurl, QString &inputFile,
inputFile = QString("/tmp/mythtv_ddp_data");
}

const QByteArray header = "Accept-Encoding";
const QByteArray value = "gzip";

MythDownloadManager *manager = GetMythDownloadManager();

if (!manager->postAuth(ddurl, &postdata, inputFile,
&::authenticationCallback, this))
if (!manager->postAuth(ddurl, &postdata, &::authenticationCallback, this,
&header, &value))
{
err_txt = QString("Could not download.");
return false;
}

QByteArray uncompressed = gUncompress(postdata);

QFile file(inputFile);
file.open(QIODevice::WriteOnly);
file.write(postdata);
file.write(uncompressed);
file.close();

#if 0
command += ".gz --header='Accept-Encoding:gzip'";

if (QFile::exists( inputFile+".gz" ))
{
command = QString("gzip -df %1").arg(inputFile+".gz");
if (myth_system(command) != GENERIC_EXIT_OK)
return false;
}
#endif

return true;
}

Expand Down Expand Up @@ -1069,8 +1065,7 @@ bool DataDirectProcessor::GrabNextSuggestedTime(void)

MythDownloadManager *manager = GetMythDownloadManager();

if (!manager->postAuth(ddurl, &postdata, resultFilename,
&::authenticationCallback, this))
if (!manager->postAuth(ddurl, &postdata, &::authenticationCallback, this))
{
LOG(VB_GENERAL, LOG_ERR, LOC +
"GrabNextSuggestedTime: Could not download");
Expand Down Expand Up @@ -2312,4 +2307,54 @@ static QString get_lineup_type(uint sourceid)
return ret;
}

QByteArray gUncompress(const QByteArray &data)
{
if (data.size() <= 4) {
LOG(VB_GENERAL, LOG_WARNING, "gUncompress: Input data is truncated");
return QByteArray();
}

QByteArray result;

int ret;
z_stream strm;
static const int CHUNK_SIZE = 1024;
char out[CHUNK_SIZE];

/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = data.size();
strm.next_in = (Bytef*)(data.data());

ret = inflateInit2(&strm, 15 + 32); // gzip decoding
if (ret != Z_OK)
return QByteArray();

// run inflate()
do {
strm.avail_out = CHUNK_SIZE;
strm.next_out = (Bytef*)(out);

ret = inflate(&strm, Z_NO_FLUSH);
Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered

switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; // and fall through
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return QByteArray();
}

result.append(out, CHUNK_SIZE - strm.avail_out);
} while (strm.avail_out == 0);

// clean up and return
inflateEnd(&strm);
return result;
}

/* vim: set expandtab tabstop=4 shiftwidth=4: */

0 comments on commit de3ade3

Please sign in to comment.