File indexing completed on 2025-01-05 05:09:30

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 "KCupsRequest.h"
0008 
0009 #include "kcupslib_log.h"
0010 
0011 #include <KLocalizedString>
0012 
0013 #include <cups/adminutil.h>
0014 #include <cups/ppd.h>
0015 
0016 #define CUPS_DATADIR QLatin1String("/usr/share/cups")
0017 
0018 KCupsRequest::KCupsRequest(KCupsConnection *connection)
0019     : m_connection(connection)
0020 {
0021     // If no connection was specified use default one
0022     if (m_connection == nullptr) {
0023         m_connection = KCupsConnection::global();
0024     }
0025     connect(this, &KCupsRequest::finished, &m_loop, &QEventLoop::quit);
0026 }
0027 
0028 QString KCupsRequest::serverError() const
0029 {
0030     switch (error()) {
0031     case IPP_SERVICE_UNAVAILABLE:
0032         return i18n("Print service is unavailable");
0033     case IPP_NOT_FOUND:
0034         return i18n("Not found");
0035     default: // In this case we don't want to map all enums
0036         qCWarning(LIBKCUPS) << "status unrecognised: " << error();
0037         return QString::fromUtf8(ippErrorString(error()));
0038     }
0039 }
0040 
0041 void KCupsRequest::getPPDS(const QString &make)
0042 {
0043     if (m_connection->readyToStart()) {
0044         KIppRequest request(CUPS_GET_PPDS, QLatin1String("/"));
0045         if (!make.isEmpty()) {
0046             request.addString(IPP_TAG_PRINTER, IPP_TAG_TEXT, KCUPS_PPD_MAKE_AND_MODEL, make);
0047         }
0048 
0049         m_ppds = m_connection->request(request, IPP_TAG_PRINTER);
0050 
0051         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0052         setFinished();
0053     } else {
0054         invokeMethod("getPPDS", make);
0055     }
0056 }
0057 
0058 static void choose_device_cb(const char *device_class, /* I - Class */
0059                              const char *device_id, /* I - 1284 device ID */
0060                              const char *device_info, /* I - Description */
0061                              const char *device_make_and_model, /* I - Make and model */
0062                              const char *device_uri, /* I - Device URI */
0063                              const char *device_location, /* I - Location */
0064                              void *user_data) /* I - Result object */
0065 {
0066     /*
0067      * Add the device to the array...
0068      */
0069     auto request = static_cast<KCupsRequest *>(user_data);
0070     QMetaObject::invokeMethod(request,
0071                               "device",
0072                               Qt::QueuedConnection,
0073                               Q_ARG(QString, QString::fromUtf8(device_class)),
0074                               Q_ARG(QString, QString::fromUtf8(device_id)),
0075                               Q_ARG(QString, QString::fromUtf8(device_info)),
0076                               Q_ARG(QString, QString::fromUtf8(device_make_and_model)),
0077                               Q_ARG(QString, QString::fromUtf8(device_uri)),
0078                               Q_ARG(QString, QString::fromUtf8(device_location)));
0079 }
0080 
0081 void KCupsRequest::getDevices(int timeout)
0082 {
0083     getDevices(timeout, QStringList(), QStringList());
0084 }
0085 
0086 void KCupsRequest::getDevices(int timeout, QStringList includeSchemes, QStringList excludeSchemes)
0087 {
0088     if (m_connection->readyToStart()) {
0089         do {
0090             const char *include;
0091             if (includeSchemes.isEmpty()) {
0092                 include = CUPS_INCLUDE_ALL;
0093             } else {
0094                 include = qUtf8Printable(includeSchemes.join(QLatin1String(",")));
0095             }
0096 
0097             const char *exclude;
0098             if (excludeSchemes.isEmpty()) {
0099                 exclude = CUPS_EXCLUDE_NONE;
0100             } else {
0101                 exclude = qUtf8Printable(excludeSchemes.join(QLatin1String(",")));
0102             }
0103 
0104             // Scan for devices for "timeout" seconds
0105             cupsGetDevices(CUPS_HTTP_DEFAULT, timeout, include, exclude, (cups_device_cb_t)choose_device_cb, this);
0106         } while (m_connection->retry("/admin/", CUPS_GET_DEVICES));
0107         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0108         setFinished(true);
0109     } else {
0110         invokeMethod("getDevices", timeout, includeSchemes, excludeSchemes);
0111     }
0112 }
0113 
0114 // THIS function can get the default server dest through the
0115 // "printer-is-default" attribute BUT it does not get user
0116 // defined default printer, see cupsGetDefault() on www.cups.org for details
0117 
0118 void KCupsRequest::getPrinters(QStringList attributes, int mask)
0119 {
0120     if (m_connection->readyToStart()) {
0121         KIppRequest request(CUPS_GET_PRINTERS, QLatin1String("/"));
0122         request.addInteger(IPP_TAG_OPERATION, IPP_TAG_ENUM, KCUPS_PRINTER_TYPE, CUPS_PRINTER_LOCAL);
0123         if (!attributes.isEmpty()) {
0124             request.addStringList(IPP_TAG_OPERATION, IPP_TAG_KEYWORD, KCUPS_REQUESTED_ATTRIBUTES, attributes);
0125         }
0126         if (mask != -1) {
0127             request.addInteger(IPP_TAG_OPERATION, IPP_TAG_ENUM, KCUPS_PRINTER_TYPE_MASK, mask);
0128         }
0129 
0130         const ReturnArguments ret = m_connection->request(request, IPP_TAG_PRINTER);
0131 
0132         for (const QVariantMap &arguments : ret) {
0133             m_printers << KCupsPrinter(arguments);
0134         }
0135 
0136         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0137         setFinished();
0138     } else {
0139         invokeMethod("getPrinters", QVariant::fromValue(attributes), mask);
0140     }
0141 }
0142 
0143 void KCupsRequest::getPrinterAttributes(const QString &printerName, bool isClass, QStringList attributes)
0144 {
0145     if (m_connection->readyToStart()) {
0146         KIppRequest request(IPP_GET_PRINTER_ATTRIBUTES, QLatin1String("/"));
0147 
0148         request.addPrinterUri(printerName, isClass);
0149         request.addInteger(IPP_TAG_OPERATION, IPP_TAG_ENUM, QLatin1String(KCUPS_PRINTER_TYPE), CUPS_PRINTER_LOCAL);
0150         request.addStringList(IPP_TAG_OPERATION, IPP_TAG_KEYWORD, QLatin1String(KCUPS_REQUESTED_ATTRIBUTES), attributes);
0151 
0152         const ReturnArguments ret = m_connection->request(request, IPP_TAG_PRINTER);
0153 
0154         for (const QVariantMap &arguments : ret) {
0155             // Inject the printer name back to the arguments hash
0156             QVariantMap args = arguments;
0157             args[KCUPS_PRINTER_NAME] = printerName;
0158             m_printers << KCupsPrinter(args);
0159         }
0160 
0161         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0162         setFinished();
0163     } else {
0164         invokeMethod("getPrinterAttributes", printerName, isClass, QVariant::fromValue(attributes));
0165     }
0166 }
0167 
0168 void KCupsRequest::getJobs(const QString &printerName, bool myJobs, int whichJobs, QStringList attributes)
0169 {
0170     if (m_connection->readyToStart()) {
0171         KIppRequest request(IPP_GET_JOBS, QLatin1String("/"));
0172 
0173         // printer-uri makes the Name of the Job and owner came blank lol
0174         request.addPrinterUri(printerName, false);
0175         request.addInteger(IPP_TAG_OPERATION, IPP_TAG_ENUM, KCUPS_PRINTER_TYPE, CUPS_PRINTER_LOCAL);
0176         request.addStringList(IPP_TAG_OPERATION, IPP_TAG_KEYWORD, KCUPS_REQUESTED_ATTRIBUTES, attributes);
0177 
0178         request.addInteger(IPP_TAG_OPERATION, IPP_TAG_ENUM, KCUPS_MY_JOBS, myJobs);
0179 
0180         if (whichJobs == CUPS_WHICHJOBS_COMPLETED) {
0181             request.addString(IPP_TAG_OPERATION, IPP_TAG_KEYWORD, KCUPS_WHICH_JOBS, QLatin1String("completed"));
0182         } else if (whichJobs == CUPS_WHICHJOBS_ALL) {
0183             request.addString(IPP_TAG_OPERATION, IPP_TAG_KEYWORD, KCUPS_WHICH_JOBS, QLatin1String("all"));
0184         }
0185 
0186         const ReturnArguments ret = m_connection->request(request, IPP_TAG_JOB);
0187 
0188         for (const QVariantMap &arguments : ret) {
0189             m_jobs << KCupsJob(arguments);
0190         }
0191 
0192         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0193         setFinished();
0194     } else {
0195         invokeMethod("getJobs", printerName, myJobs, whichJobs, QVariant::fromValue(attributes));
0196     }
0197 }
0198 
0199 void KCupsRequest::getJobAttributes(int jobId, const QString &printerUri, QStringList attributes)
0200 {
0201     if (m_connection->readyToStart()) {
0202         KIppRequest request(IPP_GET_JOB_ATTRIBUTES, QLatin1String("/"));
0203 
0204         request.addString(IPP_TAG_OPERATION, IPP_TAG_URI, KCUPS_PRINTER_URI, printerUri);
0205         request.addInteger(IPP_TAG_OPERATION, IPP_TAG_ENUM, KCUPS_PRINTER_TYPE, CUPS_PRINTER_LOCAL);
0206         request.addStringList(IPP_TAG_OPERATION, IPP_TAG_KEYWORD, KCUPS_REQUESTED_ATTRIBUTES, attributes);
0207 
0208         request.addInteger(IPP_TAG_OPERATION, IPP_TAG_INTEGER, KCUPS_JOB_ID, jobId);
0209 
0210         const ReturnArguments ret = m_connection->request(request, IPP_TAG_PRINTER);
0211 
0212         for (const QVariantMap &arguments : ret) {
0213             m_jobs << KCupsJob(arguments);
0214         }
0215 
0216         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0217         setFinished();
0218     } else {
0219         invokeMethod("getJobAttributes", jobId, printerUri, QVariant::fromValue(attributes));
0220     }
0221 }
0222 
0223 void KCupsRequest::getServerSettings()
0224 {
0225     if (m_connection->readyToStart()) {
0226         do {
0227             int num_settings;
0228             cups_option_t *settings;
0229             QVariantMap arguments;
0230             int ret = cupsAdminGetServerSettings(CUPS_HTTP_DEFAULT, &num_settings, &settings);
0231             for (int i = 0; i < num_settings; ++i) {
0232                 QString name = QString::fromUtf8(settings[i].name);
0233                 QString value = QString::fromUtf8(settings[i].value);
0234                 arguments[name] = value;
0235             }
0236             cupsFreeOptions(num_settings, settings);
0237             if (ret) {
0238                 setError(HTTP_OK, IPP_OK, QString());
0239             } else {
0240                 setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0241             }
0242 
0243             m_server = KCupsServer(arguments);
0244         } while (m_connection->retry("/admin/", -1));
0245         setFinished();
0246     } else {
0247         invokeMethod("getServerSettings");
0248     }
0249 }
0250 
0251 void KCupsRequest::getPrinterPPD(const QString &printerName)
0252 {
0253     if (m_connection->readyToStart()) {
0254         do {
0255             const char *filename;
0256             filename = cupsGetPPD2(CUPS_HTTP_DEFAULT, qUtf8Printable(printerName));
0257             qCDebug(LIBKCUPS) << filename;
0258             m_ppdFile = QString::fromUtf8(filename);
0259             qCDebug(LIBKCUPS) << m_ppdFile;
0260         } while (m_connection->retry("/", CUPS_GET_PPD));
0261         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0262         setFinished();
0263     } else {
0264         invokeMethod("getPrinterPPD", printerName);
0265     }
0266 }
0267 
0268 void KCupsRequest::setServerSettings(const KCupsServer &server)
0269 {
0270     if (m_connection->readyToStart()) {
0271         do {
0272             QVariantMap args = server.arguments();
0273             int num_settings = 0;
0274             cups_option_t *settings;
0275 
0276             QVariantMap::const_iterator i = args.constBegin();
0277             while (i != args.constEnd()) {
0278                 num_settings = cupsAddOption(qUtf8Printable(i.key()), qUtf8Printable(i.value().toString()), num_settings, &settings);
0279                 ++i;
0280             }
0281 
0282             cupsAdminSetServerSettings(CUPS_HTTP_DEFAULT, num_settings, settings);
0283             cupsFreeOptions(num_settings, settings);
0284         } while (m_connection->retry("/admin/", -1));
0285         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0286         setFinished();
0287     } else {
0288         invokeMethod("setServerSettings", QVariant::fromValue(server));
0289     }
0290 }
0291 
0292 void KCupsRequest::addOrModifyPrinter(const QString &printerName, const QVariantMap &attributes, const QString &filename)
0293 {
0294     KIppRequest request(CUPS_ADD_MODIFY_PRINTER, QLatin1String("/admin/"), filename);
0295     request.addPrinterUri(printerName);
0296     request.addVariantValues(attributes);
0297 
0298     process(request);
0299 }
0300 
0301 void KCupsRequest::addOrModifyClass(const QString &printerName, const QVariantMap &attributes)
0302 {
0303     KIppRequest request(CUPS_ADD_MODIFY_CLASS, QLatin1String("/admin/"));
0304     request.addPrinterUri(printerName, true);
0305     request.addVariantValues(attributes);
0306 
0307     process(request);
0308 }
0309 
0310 void KCupsRequest::setShared(const QString &printerName, bool isClass, bool shared)
0311 {
0312     KIppRequest request(isClass ? CUPS_ADD_MODIFY_CLASS : CUPS_ADD_MODIFY_PRINTER, QLatin1String("/admin/"));
0313     request.addPrinterUri(printerName, isClass);
0314     request.addBoolean(IPP_TAG_OPERATION, KCUPS_PRINTER_IS_SHARED, shared);
0315 
0316     process(request);
0317 }
0318 
0319 void KCupsRequest::pausePrinter(const QString &printerName)
0320 {
0321     KIppRequest request(IPP_PAUSE_PRINTER, QLatin1String("/admin/"));
0322     request.addPrinterUri(printerName);
0323 
0324     process(request);
0325 }
0326 
0327 void KCupsRequest::resumePrinter(const QString &printerName)
0328 {
0329     KIppRequest request(IPP_RESUME_PRINTER, QLatin1String("/admin/"));
0330     request.addPrinterUri(printerName);
0331 
0332     process(request);
0333 }
0334 
0335 void KCupsRequest::rejectJobs(const QString &printerName)
0336 {
0337     KIppRequest request(CUPS_REJECT_JOBS, QLatin1String("/admin/"));
0338     request.addPrinterUri(printerName);
0339 
0340     process(request);
0341 }
0342 
0343 void KCupsRequest::acceptJobs(const QString &printerName)
0344 {
0345     KIppRequest request(CUPS_ACCEPT_JOBS, QLatin1String("/admin/"));
0346     request.addPrinterUri(printerName);
0347 
0348     process(request);
0349 }
0350 
0351 void KCupsRequest::setDefaultPrinter(const QString &printerName)
0352 {
0353     KIppRequest request(CUPS_SET_DEFAULT, QLatin1String("/admin/"));
0354     request.addPrinterUri(printerName);
0355 
0356     process(request);
0357 }
0358 
0359 void KCupsRequest::deletePrinter(const QString &printerName)
0360 {
0361     KIppRequest request(CUPS_DELETE_PRINTER, QLatin1String("/admin/"));
0362     request.addPrinterUri(printerName);
0363 
0364     process(request);
0365 }
0366 
0367 void KCupsRequest::printTestPage(const QString &printerName, bool isClass)
0368 {
0369     QString resource; /* POST resource path */
0370     QString filename; /* Test page filename */
0371     QString datadir; /* CUPS_DATADIR env var */
0372 
0373     /*
0374      * Locate the test page file...
0375      */
0376     datadir = QString::fromUtf8(qgetenv("CUPS_DATADIR"));
0377     if (datadir.isEmpty()) {
0378         datadir = CUPS_DATADIR;
0379     }
0380     filename = datadir % QLatin1String("/data/testprint");
0381 
0382     /*
0383      * Point to the printer/class...
0384      */
0385     if (isClass) {
0386         resource = QLatin1String("/classes/") + printerName;
0387     } else {
0388         resource = QLatin1String("/printers/") + printerName;
0389     }
0390 
0391     KIppRequest request(IPP_PRINT_JOB, resource, filename);
0392     request.addPrinterUri(printerName);
0393     request.addString(IPP_TAG_OPERATION, IPP_TAG_NAME, KCUPS_JOB_NAME, i18n("Test Page"));
0394 
0395     process(request);
0396 }
0397 
0398 void KCupsRequest::printCommand(const QString &printerName, const QString &command, const QString &title)
0399 {
0400     if (m_connection->readyToStart()) {
0401         do {
0402             int job_id; /* Command file job */
0403             char command_file[1024]; /* Command "file" */
0404             http_status_t status; /* Document status */
0405             cups_option_t hold_option; /* job-hold-until option */
0406 
0407             /*
0408              * Create the CUPS command file...
0409              */
0410             snprintf(command_file, sizeof(command_file), "#CUPS-COMMAND\n%s\n", command.toUtf8().constData());
0411 
0412             /*
0413              * Send the command file job...
0414              */
0415             hold_option.name = const_cast<char *>("job-hold-until");
0416             hold_option.value = const_cast<char *>("no-hold");
0417 
0418             if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, qUtf8Printable(printerName), qUtf8Printable(title), 1, &hold_option)) < 1) {
0419                 qCWarning(LIBKCUPS) << "Unable to send command to printer driver!";
0420 
0421                 setError(HTTP_OK, IPP_NOT_POSSIBLE, i18n("Unable to send command to printer driver!"));
0422                 setFinished();
0423                 return;
0424             }
0425 
0426             status = cupsStartDocument(CUPS_HTTP_DEFAULT, qUtf8Printable(printerName), job_id, nullptr, CUPS_FORMAT_COMMAND, 1);
0427             if (status == HTTP_CONTINUE) {
0428                 status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, command_file, strlen(command_file));
0429             }
0430 
0431             if (status == HTTP_CONTINUE) {
0432                 cupsFinishDocument(CUPS_HTTP_DEFAULT, qUtf8Printable(printerName));
0433             }
0434 
0435             setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0436             if (httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError() >= IPP_REDIRECTION_OTHER_SITE) {
0437                 qCWarning(LIBKCUPS) << "Unable to send command to printer driver!";
0438 
0439                 cupsCancelJob(qUtf8Printable(printerName), job_id);
0440                 setFinished();
0441                 return; // Return to avoid a new try
0442             }
0443         } while (m_connection->retry("/", IPP_CREATE_JOB));
0444         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0445         setFinished();
0446     } else {
0447         invokeMethod("printCommand", printerName, command, title);
0448     }
0449 }
0450 
0451 void KCupsRequest::cancelJob(const QString &printerName, int jobId)
0452 {
0453     KIppRequest request(IPP_CANCEL_JOB, QLatin1String("/jobs/"));
0454     request.addPrinterUri(printerName);
0455     request.addInteger(IPP_TAG_OPERATION, IPP_TAG_INTEGER, KCUPS_JOB_ID, jobId);
0456 
0457     process(request);
0458 }
0459 
0460 void KCupsRequest::holdJob(const QString &printerName, int jobId)
0461 {
0462     KIppRequest request(IPP_HOLD_JOB, QLatin1String("/jobs/"));
0463     request.addPrinterUri(printerName);
0464     request.addInteger(IPP_TAG_OPERATION, IPP_TAG_INTEGER, KCUPS_JOB_ID, jobId);
0465 
0466     process(request);
0467 }
0468 
0469 void KCupsRequest::releaseJob(const QString &printerName, int jobId)
0470 {
0471     KIppRequest request(IPP_RELEASE_JOB, QLatin1String("/jobs/"));
0472     request.addPrinterUri(printerName);
0473     request.addInteger(IPP_TAG_OPERATION, IPP_TAG_INTEGER, KCUPS_JOB_ID, jobId);
0474 
0475     process(request);
0476 }
0477 
0478 void KCupsRequest::restartJob(const QString &printerName, int jobId)
0479 {
0480     KIppRequest request(IPP_RESTART_JOB, QLatin1String("/jobs/"));
0481     request.addPrinterUri(printerName);
0482     request.addInteger(IPP_TAG_OPERATION, IPP_TAG_INTEGER, KCUPS_JOB_ID, jobId);
0483 
0484     process(request);
0485 }
0486 
0487 void KCupsRequest::moveJob(const QString &fromPrinterName, int jobId, const QString &toPrinterName)
0488 {
0489     if (jobId < -1 || fromPrinterName.isEmpty() || toPrinterName.isEmpty() || jobId == 0) {
0490         qCWarning(LIBKCUPS) << "Internal error, invalid input data" << jobId << fromPrinterName << toPrinterName;
0491         setFinished();
0492         return;
0493     }
0494 
0495     KIppRequest request(CUPS_MOVE_JOB, QLatin1String("/jobs/"));
0496     request.addPrinterUri(fromPrinterName);
0497     request.addInteger(IPP_TAG_OPERATION, IPP_TAG_INTEGER, KCUPS_JOB_ID, jobId);
0498 
0499     QString toPrinterUri = KIppRequest::assembleUrif(toPrinterName, false);
0500     request.addString(IPP_TAG_OPERATION, IPP_TAG_URI, KCUPS_JOB_PRINTER_URI, toPrinterUri);
0501 
0502     process(request);
0503 }
0504 
0505 void KCupsRequest::authenticateJob(const QString &printerName, const QStringList authInfo, int jobId)
0506 {
0507     KIppRequest request(IPP_OP_CUPS_AUTHENTICATE_JOB, QLatin1String("/jobs/"));
0508     request.addPrinterUri(printerName);
0509     request.addInteger(IPP_TAG_OPERATION, IPP_TAG_INTEGER, KCUPS_JOB_ID, jobId);
0510     request.addStringList(IPP_TAG_OPERATION, IPP_TAG_TEXT, KCUPS_AUTH_INFO, authInfo);
0511 
0512     process(request);
0513 }
0514 
0515 void KCupsRequest::invokeMethod(const char *method,
0516                                 const QVariant &arg1,
0517                                 const QVariant &arg2,
0518                                 const QVariant &arg3,
0519                                 const QVariant &arg4,
0520                                 const QVariant &arg5,
0521                                 const QVariant &arg6,
0522                                 const QVariant &arg7,
0523                                 const QVariant &arg8)
0524 {
0525     m_error = IPP_OK;
0526     m_errorMsg.clear();
0527     m_printers.clear();
0528     m_jobs.clear();
0529     m_ppds.clear();
0530     m_ppdFile.clear();
0531 
0532     // If this fails we get into a infinite loop
0533     // Do not use global()->thread() which point
0534     // to the KCupsConnection parent thread
0535     moveToThread(m_connection);
0536 
0537     m_finished = !QMetaObject::invokeMethod(this,
0538                                             method,
0539                                             Qt::QueuedConnection,
0540                                             QGenericArgument(arg1.typeName(), arg1.data()),
0541                                             QGenericArgument(arg2.typeName(), arg2.data()),
0542                                             QGenericArgument(arg3.typeName(), arg3.data()),
0543                                             QGenericArgument(arg4.typeName(), arg4.data()),
0544                                             QGenericArgument(arg5.typeName(), arg5.data()),
0545                                             QGenericArgument(arg6.typeName(), arg6.data()),
0546                                             QGenericArgument(arg7.typeName(), arg7.data()),
0547                                             QGenericArgument(arg8.typeName(), arg8.data()));
0548     if (m_finished) {
0549         setError(HTTP_ERROR, IPP_BAD_REQUEST, i18n("Failed to invoke method: %1", QLatin1String(method)));
0550         setFinished();
0551     }
0552 }
0553 
0554 void KCupsRequest::process(const KIppRequest &request)
0555 {
0556     if (m_connection->readyToStart()) {
0557         m_connection->request(request);
0558 
0559         setError(httpGetStatus(CUPS_HTTP_DEFAULT), cupsLastError(), QString::fromUtf8(cupsLastErrorString()));
0560         setFinished();
0561     } else {
0562         invokeMethod("process", QVariant::fromValue(request));
0563     }
0564 }
0565 
0566 ReturnArguments KCupsRequest::ppds() const
0567 {
0568     return m_ppds;
0569 }
0570 
0571 KCupsServer KCupsRequest::serverSettings() const
0572 {
0573     return m_server;
0574 }
0575 
0576 QString KCupsRequest::printerPPD() const
0577 {
0578     return m_ppdFile;
0579 }
0580 
0581 KCupsPrinters KCupsRequest::printers() const
0582 {
0583     return m_printers;
0584 }
0585 
0586 KCupsJobs KCupsRequest::jobs() const
0587 {
0588     return m_jobs;
0589 }
0590 
0591 void KCupsRequest::waitTillFinished()
0592 {
0593     if (m_finished) {
0594         return;
0595     }
0596 
0597     m_loop.exec();
0598 }
0599 
0600 bool KCupsRequest::hasError() const
0601 {
0602     return m_error;
0603 }
0604 
0605 ipp_status_t KCupsRequest::error() const
0606 {
0607     return m_error;
0608 }
0609 
0610 http_status_t KCupsRequest::httpStatus() const
0611 {
0612     return m_httpStatus;
0613 }
0614 
0615 QString KCupsRequest::errorMsg() const
0616 {
0617     return m_errorMsg;
0618 }
0619 
0620 KCupsConnection *KCupsRequest::connection() const
0621 {
0622     return m_connection;
0623 }
0624 
0625 void KCupsRequest::setError(http_status_t httpStatus, ipp_status_t error, const QString &errorMsg)
0626 {
0627     m_httpStatus = httpStatus;
0628     m_error = error;
0629     m_errorMsg = errorMsg;
0630 }
0631 
0632 void KCupsRequest::setFinished(bool delayed)
0633 {
0634     m_finished = true;
0635     if (delayed) {
0636         QTimer::singleShot(0, this, [this]() {
0637             Q_EMIT finished(this);
0638         });
0639     } else {
0640         Q_EMIT finished(this);
0641     }
0642 }
0643 
0644 #include "moc_KCupsRequest.cpp"