File indexing completed on 2025-01-05 05:09:31
0001 /* 0002 SPDX-FileCopyrightText: 2010-2018 Daniel Nicoletti <dantti12@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "KIppRequest.h" 0008 #include "KIppRequest_p.h" 0009 0010 #include "kcupslib_log.h" 0011 0012 KIppRequest::KIppRequest() 0013 : d_ptr(new KIppRequestPrivate) 0014 { 0015 } 0016 0017 KIppRequest::KIppRequest(const KIppRequest &other) 0018 : d_ptr(new KIppRequestPrivate) 0019 { 0020 *this = other; 0021 } 0022 0023 KIppRequest::KIppRequest(ipp_op_t operation, const QString &resource, const QString &filename) 0024 : d_ptr(new KIppRequestPrivate) 0025 { 0026 Q_D(KIppRequest); 0027 0028 d->operation = operation; 0029 d->resource = resource; 0030 d->filename = filename; 0031 0032 // send our user name on the request too 0033 addString(IPP_TAG_OPERATION, IPP_TAG_NAME, QLatin1String(KCUPS_REQUESTING_USER_NAME), QString::fromUtf8(cupsUser())); 0034 } 0035 0036 KIppRequest::~KIppRequest() 0037 { 0038 delete d_ptr; 0039 } 0040 0041 ipp_op_t KIppRequest::operation() const 0042 { 0043 Q_D(const KIppRequest); 0044 return d->operation; 0045 } 0046 0047 QString KIppRequest::resource() const 0048 { 0049 Q_D(const KIppRequest); 0050 return d->resource; 0051 } 0052 0053 QString KIppRequest::filename() const 0054 { 0055 Q_D(const KIppRequest); 0056 return d->filename; 0057 } 0058 0059 ipp_t *KIppRequest::sendIppRequest() const 0060 { 0061 Q_D(const KIppRequest); 0062 0063 ipp_t *request = ippNewRequest(d->operation); 0064 0065 d->addRawRequestsToIpp(request); 0066 0067 if (d->filename.isNull()) { 0068 return cupsDoRequest(CUPS_HTTP_DEFAULT, request, qUtf8Printable(d->resource)); 0069 } else { 0070 return cupsDoFileRequest(CUPS_HTTP_DEFAULT, request, qUtf8Printable(d->resource), qUtf8Printable(d->filename)); 0071 } 0072 } 0073 0074 void KIppRequest::addString(ipp_tag_t group, ipp_tag_t valueTag, const QString &name, const QString &value) 0075 { 0076 Q_D(KIppRequest); 0077 0078 d->addRequest(group, valueTag, name, value); 0079 } 0080 0081 void KIppRequest::addStringList(ipp_tag_t group, ipp_tag_t valueTag, const QString &name, const QStringList &value) 0082 { 0083 Q_D(KIppRequest); 0084 0085 d->addRequest(group, valueTag, name, value); 0086 } 0087 0088 void KIppRequest::addInteger(ipp_tag_t group, ipp_tag_t valueTag, const QString &name, int value) 0089 { 0090 Q_D(KIppRequest); 0091 0092 d->addRequest(group, valueTag, name, value); 0093 } 0094 0095 void KIppRequest::addBoolean(ipp_tag_t group, const QString &name, bool value) 0096 { 0097 Q_D(KIppRequest); 0098 0099 d->addRequest(group, IPP_TAG_ZERO, name, value); 0100 } 0101 0102 void KIppRequest::addVariantValues(const QVariantMap &values) 0103 { 0104 auto i = values.constBegin(); 0105 while (i != values.constEnd()) { 0106 const QString &key = i.key(); 0107 const QVariant &value = i.value(); 0108 switch (value.type()) { 0109 case QVariant::Bool: 0110 // Still in use at add-printer/PageAddPrinter.cpp 0111 if (key == QLatin1String(KCUPS_PRINTER_IS_ACCEPTING_JOBS)) { 0112 addBoolean(IPP_TAG_PRINTER, key, value.toBool()); 0113 } else { 0114 addBoolean(IPP_TAG_OPERATION, key, value.toBool()); 0115 } 0116 break; 0117 case QVariant::Int: 0118 // Still in use at add-printer/PageAddPrinter.cpp 0119 if (key == QLatin1String(KCUPS_PRINTER_STATE)) { 0120 addInteger(IPP_TAG_PRINTER, IPP_TAG_ENUM, key, value.toInt()); 0121 } else { 0122 addInteger(IPP_TAG_OPERATION, IPP_TAG_ENUM, key, value.toInt()); 0123 } 0124 break; 0125 case QVariant::String: 0126 // Still in use at add-printer/* 0127 if (key == QLatin1String(KCUPS_DEVICE_URI)) { 0128 // device uri has a different TAG 0129 addString(IPP_TAG_PRINTER, IPP_TAG_URI, key, value.toString()); 0130 } else if (key == QLatin1String(KCUPS_PRINTER_OP_POLICY) || key == QLatin1String(KCUPS_PRINTER_ERROR_POLICY) || key == QLatin1String("ppd-name")) { 0131 // printer-op-policy has a different TAG 0132 addString(IPP_TAG_PRINTER, IPP_TAG_NAME, key, value.toString()); 0133 } else if (key == QLatin1String(KCUPS_JOB_NAME)) { 0134 addString(IPP_TAG_OPERATION, IPP_TAG_NAME, key, value.toString()); 0135 } else if (key == QLatin1String(KCUPS_WHICH_JOBS)) { 0136 addString(IPP_TAG_OPERATION, IPP_TAG_KEYWORD, key, value.toString()); 0137 } else { 0138 addString(IPP_TAG_PRINTER, IPP_TAG_TEXT, key, value.toString()); 0139 } 0140 break; 0141 case QVariant::StringList: 0142 if (key == QLatin1String(KCUPS_MEMBER_URIS)) { 0143 addStringList(IPP_TAG_PRINTER, IPP_TAG_URI, key, value.toStringList()); 0144 } else { 0145 addStringList(IPP_TAG_PRINTER, IPP_TAG_NAME, key, value.toStringList()); 0146 } 0147 break; 0148 case QVariant::UInt: 0149 addInteger(IPP_TAG_OPERATION, IPP_TAG_ENUM, key, value.toInt()); 0150 break; 0151 default: 0152 qCWarning(LIBKCUPS) << "type NOT recognized! This will be ignored:" << key << "values" << i.value(); 0153 } 0154 ++i; 0155 } 0156 } 0157 0158 void KIppRequest::addPrinterUri(const QString &printerName, bool isClass) 0159 { 0160 QString uri = assembleUrif(printerName, isClass); 0161 addString(IPP_TAG_OPERATION, IPP_TAG_URI, QLatin1String(KCUPS_PRINTER_URI), uri); 0162 } 0163 0164 QString KIppRequest::assembleUrif(const QString &name, bool isClass) 0165 { 0166 char uri[HTTP_MAX_URI]; // printer URI 0167 0168 QString destination; 0169 if (isClass) { 0170 destination = QLatin1String("/classes/") + name; 0171 } else { 0172 destination = QLatin1String("/printers/") + name; 0173 } 0174 0175 httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", cupsUser(), "localhost", ippPort(), destination.toUtf8().constData()); 0176 return QString::fromLatin1(uri); 0177 } 0178 0179 KIppRequest &KIppRequest::operator=(const KIppRequest &other) 0180 { 0181 Q_D(KIppRequest); 0182 if (this == &other) 0183 return *this; 0184 0185 *d = *other.d_ptr; 0186 0187 return *this; 0188 } 0189 0190 void KIppRequestPrivate::addRequest(ipp_tag_t group, ipp_tag_t valueTag, const QString &name, const QVariant &value) 0191 { 0192 KCupsRawRequest request; 0193 request.group = group; 0194 request.valueTag = valueTag; 0195 request.name = name; 0196 request.value = value; 0197 0198 rawRequests << request; 0199 } 0200 0201 void KIppRequestPrivate::addRawRequestsToIpp(ipp_t *ipp) const 0202 { 0203 // sort the values as CUPS requires it 0204 std::sort(rawRequests.begin(), rawRequests.end(), [](const KCupsRawRequest &a, const KCupsRawRequest &b) { 0205 return a.group < b.group; 0206 }); 0207 0208 const QList<KCupsRawRequest> &requests = rawRequests; 0209 for (const KCupsRawRequest &request : requests) { 0210 switch (request.value.type()) { 0211 case QVariant::Bool: 0212 ippAddBoolean(ipp, request.group, request.name.toUtf8().constData(), request.value.toBool()); 0213 break; 0214 case QVariant::Int: 0215 case QVariant::UInt: 0216 ippAddInteger(ipp, request.group, request.valueTag, request.name.toUtf8().constData(), request.value.toInt()); 0217 break; 0218 case QVariant::String: 0219 ippAddString(ipp, request.group, request.valueTag, request.name.toUtf8().constData(), "utf-8", request.value.toString().toUtf8().constData()); 0220 break; 0221 case QVariant::StringList: { 0222 QStringList list = request.value.toStringList(); 0223 QList<QByteArray> valuesQByteArrayList; 0224 const char **values = qStringListToCharPtrPtr(list, valuesQByteArrayList); 0225 0226 ippAddStrings(ipp, request.group, request.valueTag, request.name.toUtf8().constData(), list.size(), "utf-8", values); 0227 0228 // ippAddStrings deep copies everything so we can throw away the values. 0229 // the QBAList and content is auto discarded when going out of scope. 0230 delete[] values; 0231 break; 0232 } 0233 default: 0234 qCWarning(LIBKCUPS) << "type NOT recognized! This will be ignored:" << request.name << "values" << request.value; 0235 } 0236 } 0237 }