harbour-seaprint/src/ippprinter.cpp

370 lines
11 KiB
C++
Raw Normal View History

2019-12-01 22:27:00 +03:00
#include "ippprinter.h"
2020-01-20 22:11:41 +03:00
#include <seaprint_version.h>
2020-05-03 15:13:44 +03:00
#include "mimer.h"
2019-12-01 22:27:00 +03:00
IppPrinter::IppPrinter()
{
_nam = new QNetworkAccessManager(this);
2019-12-08 15:55:56 +03:00
_print_nam = new QNetworkAccessManager(this);
_jobs_nam = new QNetworkAccessManager(this);
2019-12-12 22:53:46 +03:00
_job_cancel_nam = new QNetworkAccessManager(this);
2019-12-01 22:27:00 +03:00
connect(_nam, SIGNAL(finished(QNetworkReply*)),this, SLOT(getPrinterAttributesFinished(QNetworkReply*)));
2020-01-04 13:55:22 +03:00
connect(_nam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreKnownSslErrors(QNetworkReply*, const QList<QSslError>&)));
2019-12-08 15:55:56 +03:00
connect(_print_nam, SIGNAL(finished(QNetworkReply*)),this, SLOT(printRequestFinished(QNetworkReply*)));
2020-01-04 13:55:22 +03:00
connect(_print_nam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreKnownSslErrors(QNetworkReply*, const QList<QSslError>&)));
2019-12-08 15:55:56 +03:00
connect(_jobs_nam, SIGNAL(finished(QNetworkReply*)),this, SLOT(getJobsRequestFinished(QNetworkReply*)));
2020-01-04 13:55:22 +03:00
connect(_jobs_nam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreKnownSslErrors(QNetworkReply*, const QList<QSslError>&)));
2019-12-12 22:53:46 +03:00
connect(_job_cancel_nam, SIGNAL(finished(QNetworkReply*)),this, SLOT(cancelJobFinished(QNetworkReply*)));
2020-01-04 13:55:22 +03:00
connect(_job_cancel_nam, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(ignoreKnownSslErrors(QNetworkReply*, const QList<QSslError>&)));
2019-12-01 22:27:00 +03:00
QObject::connect(this, &IppPrinter::urlChanged, this, &IppPrinter::onUrlChanged);
2020-05-01 14:49:17 +03:00
qRegisterMetaType<QTemporaryFile*>("QTemporaryFile*");
_worker = new ConvertWorker;
_worker->moveToThread(&_workerThread);
connect(&_workerThread, &QThread::finished, _worker, &QObject::deleteLater);
connect(this, &IppPrinter::doConvertPdf, _worker, &ConvertWorker::convertPdf);
connect(_worker, &ConvertWorker::done, this, &IppPrinter::convertDone);
connect(_worker, &ConvertWorker::failed, this, &IppPrinter::convertFailed);
_workerThread.start();
2019-12-01 22:27:00 +03:00
}
IppPrinter::~IppPrinter() {
delete _nam;
2019-12-08 15:55:56 +03:00
delete _print_nam;
delete _jobs_nam;
2019-12-12 22:53:46 +03:00
delete _job_cancel_nam;
}
QJsonObject IppPrinter::opAttrs() {
QJsonObject o
{
{"attributes-charset", QJsonObject {{"tag", IppMsg::Charset}, {"value", "utf-8"}}},
{"attributes-natural-language", QJsonObject {{"tag", IppMsg::NaturalLanguage}, {"value", "en-us"}}},
{"printer-uri", QJsonObject {{"tag", IppMsg::Uri}, {"value", _url.toString()}}},
2019-12-12 22:53:46 +03:00
{"requesting-user-name", QJsonObject {{"tag", IppMsg::NameWithoutLanguage}, {"value", "nemo"}}},
};
return o;
2019-12-01 22:27:00 +03:00
}
void IppPrinter::setUrl(QString url_s)
2019-12-01 22:27:00 +03:00
{
QUrl url = QUrl(url_s);
qDebug() << url.scheme();
if(url.scheme() != "ipp" /* or ipps */)
{
//if https -> ipps, else:
if(url.scheme() == "")
{
url = QUrl("ipp://"+url_s); // Why isn't setScheme working?
}
else if (url.scheme() == "http") {
url.setScheme("ipp");
}
else {
url = QUrl();
}
}
qDebug() << url_s << url;
2019-12-01 22:27:00 +03:00
if(url != _url)
{
_url = url;
emit urlChanged();
}
}
void IppPrinter::onUrlChanged()
{
2019-12-17 22:20:09 +03:00
refresh();
}
void IppPrinter::refresh() {
2019-12-01 22:27:00 +03:00
_attrs = QJsonObject();
emit attrsChanged();
QNetworkRequest request;
request.setUrl(httpUrl());
2019-12-01 22:27:00 +03:00
// request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
2020-01-20 22:11:41 +03:00
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint "SEAPRINT_VERSION);
2019-12-01 22:27:00 +03:00
2019-12-12 22:53:46 +03:00
QJsonObject o = opAttrs();
2019-12-01 22:27:00 +03:00
IppMsg msg = IppMsg(o);
_nam->post(request, msg.encode(IppMsg::GetPrinterAttrs));
}
void IppPrinter::getPrinterAttributesFinished(QNetworkReply *reply)
{
2019-12-08 15:55:56 +03:00
qDebug() << reply->error() << reply->errorString() << reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString();
_attrs = QJsonObject();
2019-12-01 22:27:00 +03:00
if(reply->error() == QNetworkReply::NoError)
{
try {
IppMsg resp(reply);
2019-12-08 15:55:56 +03:00
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getPrinterAttrs();
2019-12-01 22:27:00 +03:00
_attrs = resp.getPrinterAttrs();
}
catch(std::exception e)
{
qDebug() << e.what();
}
}
emit attrsChanged();
2019-12-01 22:27:00 +03:00
}
2019-12-08 15:55:56 +03:00
void IppPrinter::printRequestFinished(QNetworkReply *reply)
2019-12-01 22:27:00 +03:00
{
2019-12-17 22:18:57 +03:00
_jobAttrs = QJsonObject();
bool status = false;
2019-12-01 22:27:00 +03:00
if(reply->error() == QNetworkReply::NoError)
{
try {
IppMsg resp(reply);
2019-12-06 22:18:48 +03:00
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
2019-12-08 15:55:56 +03:00
_jobAttrs = resp.getJobAttrs()[0].toObject();
2019-12-17 22:18:57 +03:00
status = resp.getStatus() <= 0xff;
2019-12-01 22:27:00 +03:00
}
catch(std::exception e)
{
qDebug() << e.what();
}
}
2019-12-17 22:18:57 +03:00
else {
_jobAttrs.insert("job-state-message", QJsonObject {{"tag", IppMsg::TextWithoutLanguage}, {"value", "Network error"}});
}
emit jobAttrsChanged();
2020-04-04 14:56:36 +03:00
emit jobFinished(status);
2019-12-01 22:27:00 +03:00
}
2019-12-08 15:55:56 +03:00
void IppPrinter::getJobsRequestFinished(QNetworkReply *reply)
{
if(reply->error() == QNetworkReply::NoError)
{
try {
IppMsg resp(reply);
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
_jobs = resp.getJobAttrs();
emit jobsChanged();
}
catch(std::exception e)
{
qDebug() << e.what();
}
}
}
2019-12-01 22:27:00 +03:00
2019-12-12 22:53:46 +03:00
void IppPrinter::cancelJobFinished(QNetworkReply *reply)
{
2020-02-23 15:11:28 +03:00
bool status = false;
2019-12-12 22:53:46 +03:00
if(reply->error() == QNetworkReply::NoError)
{
try {
IppMsg resp(reply);
qDebug() << resp.getStatus() << resp.getOpAttrs() << resp.getJobAttrs();
2020-02-23 15:11:28 +03:00
status = resp.getStatus() <= 0xff;
2019-12-12 22:53:46 +03:00
}
catch(std::exception e)
{
qDebug() << e.what();
}
}
2020-02-23 15:11:28 +03:00
emit cancelStatus(status);
2019-12-12 22:53:46 +03:00
getJobs();
}
2020-01-04 13:55:22 +03:00
void IppPrinter::ignoreKnownSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
{
QList<QSslError> IgnoredSslErrors = {QSslError::NoError,
QSslError::SelfSignedCertificate,
QSslError::HostNameMismatch,
QSslError::UnableToGetLocalIssuerCertificate,
QSslError::UnableToVerifyFirstCertificate
};
qDebug() << errors;
for (QList<QSslError>::const_iterator it = errors.constBegin(); it != errors.constEnd(); it++) {
if(!IgnoredSslErrors.contains(it->error())) {
qDebug() << "Bad error: " << int(it->error()) << it->error();
return;
}
}
// For whatever reason, it doesn't work to pass IgnoredSslErrors here
reply->ignoreSslErrors(errors);
}
void IppPrinter::convertDone(QNetworkRequest request, QTemporaryFile* data)
2020-05-01 14:49:17 +03:00
{
connect(_print_nam, SIGNAL(finished(QNetworkReply*)), data, SLOT(deleteLater()));
2020-05-01 14:49:17 +03:00
data->open();
_print_nam->post(request, data);
}
void IppPrinter::convertFailed()
{
_jobAttrs = QJsonObject();
_jobAttrs.insert("job-state-message", QJsonObject {{"tag", IppMsg::TextWithoutLanguage}, {"value", "Internal error"}});
emit jobAttrsChanged();
emit jobFinished(false);
}
2020-01-04 13:55:22 +03:00
2020-04-04 14:56:36 +03:00
void IppPrinter::print(QJsonObject attrs, QString filename){
2019-12-01 22:27:00 +03:00
qDebug() << "printing" << filename << attrs;
QFile file(filename);
bool file_ok = file.open(QIODevice::ReadOnly);
if(!file_ok)
2020-04-04 14:56:36 +03:00
{
emit jobFinished(false);
return;
}
2019-12-01 22:27:00 +03:00
QFileInfo fileinfo(file);
2019-12-12 22:53:46 +03:00
QJsonObject o = opAttrs();
o.insert("job-name", QJsonObject {{"tag", IppMsg::NameWithoutLanguage}, {"value", fileinfo.fileName()}});
2019-12-01 22:27:00 +03:00
2019-12-06 22:18:48 +03:00
// Only include if printer supports it
// if (filename.endsWith("pdf"))
// {
// attrs.insert("document-format", QJsonObject {{"tag", 73}, {"value", "application/pdf"}});
// }
// else if (filename.endsWith("jpg")) {
// attrs.insert("document-format", QJsonObject {{"tag", 73}, {"value", "image/jpeg"}});
// }
2019-12-07 16:40:36 +03:00
qDebug() << "Printing job" << o << attrs;
2019-12-01 22:27:00 +03:00
IppMsg job = IppMsg(o, attrs);
QByteArray contents = job.encode(IppMsg::PrintJob);
2020-01-26 14:08:57 +03:00
QNetworkRequest request;
request.setUrl(httpUrl());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint "SEAPRINT_VERSION);
2020-05-03 15:13:44 +03:00
Mimer* mimer = Mimer::instance();
QString mimeType = mimer->get_type(filename);
ConvertFrom from = NotConvertable;
ConvertTarget target = NoConvert;
if(mimeType == "application/pdf")
{
from = Pdf;
}
else if (mimeType.contains("image")) {
// from = Image; TODO: handle image conversions
}
QJsonArray supportedMimeTypes = _attrs["document-format-supported"].toObject()["value"].toArray();
qDebug() << supportedMimeTypes << supportedMimeTypes.contains(mimeType);
2020-05-05 21:07:21 +03:00
if(from == Pdf /*&& !supportedMimeTypes.contains("application/pdf")*/)
2020-05-03 15:13:44 +03:00
{
if(supportedMimeTypes.contains("image/pwg-raster"))
{
target = PwgConvert;
}
else if (supportedMimeTypes.contains("image/urf"))
{
target = UrfConvert;
}
}
if(from == Pdf && target != NoConvert)
2020-01-26 14:08:57 +03:00
{
file.close();
QTemporaryFile* tempfile = new QTemporaryFile();
tempfile->open();
tempfile->write(contents);
qDebug() << tempfile->fileName();
tempfile->close();
2020-05-03 15:13:44 +03:00
emit doConvertPdf(request, filename, target==UrfConvert, tempfile);
2020-01-26 14:08:57 +03:00
}
2020-05-03 15:13:44 +03:00
else
{
2020-01-26 14:08:57 +03:00
QByteArray filedata = file.readAll();
contents = contents.append(filedata);
file.close();
_print_nam->post(request, contents);
}
return;
2019-12-01 22:27:00 +03:00
}
2019-12-08 15:55:56 +03:00
bool IppPrinter::getJobs() {
qDebug() << "getting jobs";
2019-12-12 22:53:46 +03:00
QJsonObject o = opAttrs();
2020-01-03 15:37:51 +03:00
o.insert("requested-attributes", QJsonObject {{"tag", IppMsg::Keyword}, {"value", "all"}});
2019-12-08 15:55:56 +03:00
IppMsg job = IppMsg(o, QJsonObject());
QNetworkRequest request;
QByteArray contents = job.encode(IppMsg::GetJobs);
request.setUrl(httpUrl());
2019-12-08 15:55:56 +03:00
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
2020-01-20 22:11:41 +03:00
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint "SEAPRINT_VERSION);
2019-12-08 15:55:56 +03:00
_jobs_nam->post(request, contents);
return true;
}
2019-12-12 22:53:46 +03:00
bool IppPrinter::cancelJob(qint32 jobId) {
2020-02-23 15:11:28 +03:00
qDebug() << "cancelling jobs";
2019-12-08 15:55:56 +03:00
2019-12-12 22:53:46 +03:00
QJsonObject o = opAttrs();
o.insert("job-id", QJsonObject {{"tag", IppMsg::Integer}, {"value", jobId}});
IppMsg job = IppMsg(o, QJsonObject());
QNetworkRequest request;
QByteArray contents = job.encode(IppMsg::CancelJob);
request.setUrl(httpUrl());
2019-12-12 22:53:46 +03:00
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/ipp");
2020-01-20 22:11:41 +03:00
request.setHeader(QNetworkRequest::UserAgentHeader, "SeaPrint "SEAPRINT_VERSION);
2019-12-12 22:53:46 +03:00
_job_cancel_nam->post(request, contents);
return true;
}
QUrl IppPrinter::httpUrl() {
QUrl url = _url;
url.setScheme("http");
if(url.port() == -1) {
url.setPort(631);
}
return url;
}