harbour-seaprint/src/ippmsg.cpp
2020-02-23 10:54:35 +01:00

290 lines
7.3 KiB
C++

#include "ippmsg.h"
#define MAJ_VSN 1
#define MIN_VSN 1
quint32 IppMsg::_reqid=1;
IppMsg::IppMsg()
{
}
IppMsg::IppMsg(QJsonObject opAttrs, QJsonObject jobAttrs)
{
_opAttrs = opAttrs;
_jobAttrs = QJsonArray {jobAttrs};
}
IppMsg::~IppMsg()
{
}
IppMsg::IppMsg(QNetworkReply* resp)
{
QByteArray tmp = resp->readAll();
Bytestream bts(tmp.constData(), tmp.length());
quint8 majVsn;
quint8 minVsn;
quint32 reqId;
bts >> majVsn >> minVsn >> _status >> reqId;
QJsonObject attrs;
IppMsg::IppTag currentAttrType = IppTag::EndAttrs;
QString last_name;
while(!bts.atEnd())
{
if(bts.peekU8() <= IppTag::PrinterAttrs) {
if(currentAttrType == IppTag::OpAttrs) {
_opAttrs = attrs;
}
else if (currentAttrType == IppTag::JobAttrs) {
_jobAttrs.append(attrs);
}
else if (currentAttrType == IppTag::PrinterAttrs) {
_printerAttrs = attrs;
}
if(bts >>= (uint8_t)IppTag::EndAttrs) {
break;
}
currentAttrType = (IppTag)bts.getU8();
attrs = QJsonObject();
}
else {
last_name = consume_attribute(attrs, bts, last_name);
}
}
}
QString IppMsg::consume_attribute(QJsonObject& attrs, Bytestream& data, QString lastName)
{
quint8 tag;
quint16 tmp_len;
QString name;
QJsonValue value;
std::string tmp_str = "";
bool noList = false;
data >> tag >> tmp_len;
data/tmp_len >> tmp_str;
name = tmp_str!="" ? tmp_str.c_str() : lastName;
switch (tag) {
case OpAttrs:
case JobAttrs:
case EndAttrs:
case PrinterAttrs:
Q_ASSERT(false);
case Integer:
case Enum:
quint32 tmp_u32;
data >> tmp_len >> tmp_u32;
value = (int)tmp_u32;
break;
case Boolean:
quint8 tmp_bool;
data >> tmp_len >> tmp_bool;
value = (bool)tmp_bool;
noList = true;
break;
case DateTime:
{
quint16 year;
quint8 month, day, hour, minutes, seconds, deci_seconds,
plus_minus, utc_h_offset, utc_m_offset;
data >> tmp_len >> year >> month >> day >> hour >> minutes >> seconds >> deci_seconds
>> plus_minus >> utc_h_offset >> utc_m_offset;
QDate date(year, month, day);
QTime time(hour, minutes, seconds, deci_seconds*100);
int offset_seconds = (plus_minus == '+' ? 1 : -1)*(utc_h_offset*60*60+utc_m_offset*60);
value = QDateTime(date, time, Qt::OffsetFromUTC, offset_seconds).toString(Qt::ISODate);
break;
}
case Resolution:
{
qint32 x, y;
qint8 units;
QJsonObject tmp_res;
data >> tmp_len >> x >> y >> units;
tmp_res.insert("x", x);
tmp_res.insert("y", y);
tmp_res.insert("units", units);
value = tmp_res;
break;
}
case IntegerRange:
{
qint32 low, high;
data >> tmp_len >> low >> high;
QJsonObject tmp_range;
tmp_range.insert("low", low);
tmp_range.insert("high", high);
value = tmp_range;
noList = true;
break;
}
case OctetStringUnknown:
case TextWithLanguage:
case NameWithLanguage:
case TextWithoutLanguage:
case NameWithoutLanguage:
case Keyword:
case Uri:
case UriScheme:
case Charset:
case NaturalLanguage:
case MimeMediaType:
default:
data >> tmp_len;
data/tmp_len >> tmp_str;
value = tmp_str.c_str();
break;
};
if(attrs.contains(name))
{
QJsonObject tmp = attrs[name].toObject();
QJsonArray tmpa;
if(tmp["value"].isArray())
{
tmpa = tmp["value"].toArray();
}
else
{
tmpa = QJsonArray {tmp["value"]};
}
tmpa.append(value);
tmp["value"] = tmpa;
attrs.insert(name, tmp);
}
else
{
if((name.endsWith("-supported") || name == "printer-icons") && !noList)
{
value = QJsonArray {value};
}
attrs.insert(name, QJsonObject {{"tag", tag}, {"value", value}});
}
return name;
}
QByteArray IppMsg::encode(Operation op)
{
Bytestream ipp;
ipp << quint8(MAJ_VSN) << quint8(MIN_VSN);
ipp << quint16(op);
ipp << _reqid++;
if(!_opAttrs.empty())
{
ipp << quint8(1);
for(QJsonObject::iterator it = _opAttrs.begin(); it != _opAttrs.end(); it++)
{
QJsonObject val = it.value().toObject();
ipp << encode_attr(val["tag"].toInt(), it.key(), val["value"]);
}
}
for(QJsonArray::iterator ait = _jobAttrs.begin(); ait != _jobAttrs.begin(); ait++)
{
ipp << quint8(2);
QJsonObject tmpObj = ait->toObject();
for(QJsonObject::iterator it = tmpObj.begin(); it != tmpObj.end(); it++)
{
QJsonObject val = it.value().toObject();
ipp << encode_attr(val["tag"].toInt(), it.key(), val["value"]);
}
}
ipp << quint8(3);
return QByteArray((char*)(ipp.raw()), ipp.size());
}
Bytestream IppMsg::encode_attr(quint8 tag, QString name, QJsonValueRef value)
{
Bytestream req;
switch (tag) {
case OpAttrs:
case JobAttrs:
case EndAttrs:
case PrinterAttrs:
Q_ASSERT(false);
case Integer:
case Enum:
{
quint32 tmp_u32 = value.toInt();
req << (quint16)4 << tmp_u32;
break;
}
case Boolean:
{
quint32 tmp_u8 = value.toBool();
req << (quint16)1 << tmp_u8;
break;
}
case DateTime:
{
Q_ASSERT("fixme");
break;
}
case Resolution:
{
qDebug() << value << value.toObject();
qint32 x = value.toObject()["x"].toInt();
qint32 y = value.toObject()["y"].toInt();
qint8 units = value.toObject()["units"].toInt();
req << (quint16)9 << x << y << units;
break;
}
case IntegerRange:
{
qint32 low = value.toObject()["low"].toInt();
qint32 high = value.toObject()["high"].toInt();
req << (quint16)8 << low << high;
break;
}
case OctetStringUnknown:
case TextWithLanguage:
case NameWithLanguage:
case TextWithoutLanguage:
case NameWithoutLanguage:
case Keyword:
case Uri:
case UriScheme:
case Charset:
case NaturalLanguage:
case MimeMediaType:
{
QByteArray tmpstr = value.toString().toUtf8();
req << quint16(tmpstr.length());
req.putBytes(tmpstr.data(), tmpstr.length());
break;
}
default:
qDebug() << "uncaught tag" << tag;
Q_ASSERT(false);
break;
}
Bytestream actual;
if(req.size() != 0)
{
actual << tag << quint16(name.length()) << name.toStdString() << req;
}
return actual;
}