Friendiqa/source-android/common/xhr.cpp

369 lines
11 KiB
C++

// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// 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. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "xhr.h"
#include <QHttpPart>
#include <QTextCodec>
#include <QUrlQuery>
#include <QList>
#include <QDataStream>
#include <QJsonDocument>
#include <QJsonObject>
#include "uploadableimage.h"
XHR *XHR::instance()
{
static XHR xhr;
return &xhr;
}
XHR::XHR(QObject *parent) : QObject(parent)
{
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
}
void XHR::setUrl(QString url)
{
if (url!=m_url) {
m_url = url;
emit urlChanged();
}
}
void XHR::setApi(QString api)
{
if (api!=m_api) {
m_api = api;
emit apiChanged();
}
}
void XHR::setLogin(QString login)
{
if (login!=m_login) {
m_login = login;
emit loginChanged();
}
}
void XHR::setFilename(QString filename)
{
if (filename!=m_filename) {
m_filename = filename;
emit filenameChanged();
}
}
void XHR::setContactlist(QList<QString> contactlist)
{
if (contactlist!=m_contactlist) {
m_contactlist = contactlist;
emit contactlistChanged();
}
}
void XHR::setFilelist(QList<QString> filelist)
{
if (filelist!=m_filelist) {
m_filelist = filelist;
emit filelistChanged();
}
}
void XHR::setImagedir(QString imagedir)
{
if (imagedir!=m_imagedir) {
m_imagedir = imagedir;
emit imagedirChanged();
}
}
void XHR::setDownloadtype(QString downloadtype)
{
if (downloadtype!=m_downloadtype) {
m_downloadtype = downloadtype;
emit downloadtypeChanged();
}
}
QString XHR::url() const
{
return m_url;
}
QString XHR::api() const
{
return m_api;
}
QString XHR::login() const
{
return m_login;
}
QString XHR::filename() const
{
return m_filename;
}
QList<QString> XHR::contactlist() const
{
return m_contactlist;
}
QList<QString> XHR::filelist() const
{
return m_filelist;
}
QString XHR::imagedir() const
{
return m_imagedir;
}
QString XHR::downloadtype() const
{
return m_downloadtype;
}
QString XHR::networktype() const
{
return nc.bearerTypeFamily() + nc.bearerTypeName();
}
void XHR::setParam(QString name, QString value)
{
params.insert(name, value);
}
void XHR::setImageFileParam(QString name, QString url)
{
files.insert(name, url);
}
void XHR::clearParams()
{
files.clear();
params.clear();
}
void XHR::download()
{
QUrl requrl(m_url);
if(m_downloadtype=="picturelist"){
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
}
request.setUrl(requrl);
//qDebug() << requrl;
reply = manager.get(request);
reply->ignoreSslErrors();
connect(reply, &QNetworkReply::readyRead,this, &XHR::onReadyRead);
//connect(reply,SIGNAL(downloadProgress(qint64,qint64)), this,SLOT(updateDownloadProgress(qint64,qint64)));
connect(reply, &QNetworkReply::finished,this, &XHR::onRequestFinished);
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
}
void XHR::get()
{
QUrlQuery query;
QHashIterator<QString, QString> i(params);
while(i.hasNext()) {
i.next();
query.addQueryItem(i.key(), i.value());
}
QUrl requrl(m_url+m_api);
//qDebug() << requrl;
requrl.setQuery(query);
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader("Authorization", headerData.toLocal8Bit());
request.setUrl(requrl);
reply = manager.get(request);
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
}
void XHR::getlist()
{
if(dlindex < m_filelist.size()) {
QString cleanfilename;
if (m_downloadtype=="contactlist"){cleanfilename = m_contactlist.at(dlindex)+"-"+ m_filelist.at(dlindex).section('/',-1).section('?',0,0);
XHR::setFilename(imagedir()+"contacts/"+cleanfilename);
XHR::setUrl(m_filelist.at(dlindex));}
else {
XHR::setUrl(m_filelist.at(dlindex));}
XHR::download();
} else {dlindex=0;}
}
void XHR::post()
{
//qDebug() << "start post to " << m_url;
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHashIterator<QString, QString> iparams(params);
while(iparams.hasNext()) {
iparams.next();
//qDebug() << "\t add param " << iparams.key() << " : " << iparams.value();
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + iparams.key() + "\""));
textPart.setBody(iparams.value().toUtf8());
multiPart->append(textPart);
}
UploadableImage uimg;
QHashIterator<QString, QString> ifiles(files);
while(ifiles.hasNext()) {
ifiles.next();
uimg.setSource(ifiles.value());
//qDebug() << "\t image: " << uimg.mimetype() << ", " << ifiles.key();
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(uimg.mimetype()));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + ifiles.key() + "\"; filename=\""+uimg.filename()+"\""));
imagePart.setBody(uimg.bytes());
multiPart->append(imagePart);
}
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
request.setRawHeader(QByteArray("Authorization"), headerData.toLocal8Bit());
request.setUrl(m_url+m_api);
reply = manager.post(request, multiPart);
qDebug() << "\t request sent";
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
qDebug() << "\t reply signals connected";
}
void XHR::onReplyError(QNetworkReply::NetworkError code)
{
qDebug() << code;
emit this->error( bufferToString(), m_url,m_api, (int) code);
buffer.clear();
reply->deleteLater();
}
void XHR::onReplySuccess()
{
qDebug() << "!";
emit this->success(buffer, m_api);
buffer.clear();
// reply->deleteLater();
}
void XHR::onRequestFinished()
{
// Save the file here
if (buffer.isNull()){qDebug() << "File empty"<<m_url; buffer.clear(); emit this->error(m_downloadtype,m_url,m_api,1);}
else if (m_downloadtype=="picturelist") {
QJsonDocument jsonResponse = QJsonDocument::fromJson(buffer);
QJsonObject jsonObject = jsonResponse.object();
int arraystart=buffer.indexOf('{"data":"')+8;
int arraylength=buffer.indexOf('"',9)-arraystart;
QByteArray b64=buffer.mid(arraystart,arraylength);
QString helpfilename=jsonObject["filename"].toString();
QString helpfile=helpfilename.left(helpfilename.lastIndexOf("."));
QString filesuffix="";
if (jsonObject["type"].toString()=="image/jpeg"){filesuffix=".jpg";}
else if (jsonObject["type"].toString()=="image/png"){filesuffix=".png";}
else {filesuffix="";}
if (helpfilename==""){// check if file has any filename
helpfile=jsonObject["id"].toString();
setFilename(imagedir()+"albums/"+jsonObject["album"].toString()+"/"+jsonObject["id"].toString()+filesuffix);
}
else{setFilename(imagedir()+"albums/"+jsonObject["album"].toString()+"/"+helpfile+filesuffix);}
//qDebug()<<"Filename "<<m_filename;
QFile file(m_filename);
file.open(QIODevice::WriteOnly);
file.write(QByteArray::fromBase64(b64));
buffer.clear();
b64.clear();
file.close();
jsonObject["data"]="";
jsonObject["filename"]=helpfile+filesuffix;
emit this->downloadedjson(m_downloadtype,m_url,m_filename,dlindex,jsonObject);
if(downloadtype()=="picturelist"){dlindex=dlindex+1;XHR::getlist();}
}
else {
QFile file(m_filename);
file.open(QIODevice::WriteOnly);
file.write(buffer);
buffer.clear();
file.close();
emit this->downloaded(m_downloadtype,m_url,m_filename,dlindex);
if(downloadtype()=="contactlist"){dlindex=dlindex+1;XHR::getlist();}
//reply->deleteLater();
}
}
void XHR::onReadyRead()
{
qDebug() << ".";
buffer += reply->readAll();
}
//void XHR::updateDownloadProgress(qint64 bytesRead, qint64 totalBytes)
//{
// qDebug() << "Bytes: " << bytesRead<<" / "<<totalBytes;
//}
void XHR::onSSLError(const QList<QSslError> &errors)
{
qDebug() << "XHR::onSSLError :" ;
QListIterator<QSslError> ierrs(errors);
while(ierrs.hasNext()) {
qDebug() << "\t" << ierrs.next().errorString();
}
}
QString XHR::bufferToString()
{
return QTextCodec::codecForName("utf-8")->toUnicode(buffer);
}