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 #ifndef KCUPSCONNECTION_H
0008 #define KCUPSCONNECTION_H
0009 
0010 #include <QMetaMethod>
0011 #include <QMutex>
0012 #include <QStringList>
0013 #include <QThread>
0014 #include <QTimer>
0015 #include <QUrl>
0016 #include <QVariantMap>
0017 #include <QWidget>
0018 
0019 #include <kcupslib_export.h>
0020 
0021 #include <cups/cups.h>
0022 
0023 #define KCUPS_DEVICE_CLASS QLatin1String("device-class")
0024 #define KCUPS_DEVICE_ID QLatin1String("device-id")
0025 #define KCUPS_DEVICE_INFO QLatin1String("device-info")
0026 #define KCUPS_DEVICE_MAKE_AND_MODEL QLatin1String("device-make-and-model")
0027 #define KCUPS_DEVICE_LOCATION QLatin1String("device-location")
0028 #define KCUPS_DEVICE_URI QLatin1String("device-uri")
0029 
0030 #define KCUPS_PRINTER_NAME QLatin1String("printer-name")
0031 #define KCUPS_PRINTER_LOCATION QLatin1String("printer-location")
0032 #define KCUPS_PRINTER_INFO QLatin1String("printer-info")
0033 #define KCUPS_PRINTER_URI QLatin1String("printer-uri")
0034 #define KCUPS_PRINTER_MAKE_AND_MODEL QLatin1String("printer-make-and-model")
0035 #define KCUPS_PRINTER_STATE QLatin1String("printer-state")
0036 #define KCUPS_PRINTER_STATE_MESSAGE QLatin1String("printer-state-message")
0037 #define KCUPS_PRINTER_IS_SHARED QLatin1String("printer-is-shared")
0038 #define KCUPS_PRINTER_IS_ACCEPTING_JOBS QLatin1String("printer-is-accepting-jobs")
0039 #define KCUPS_PRINTER_TYPE QLatin1String("printer-type")
0040 #define KCUPS_PRINTER_TYPE_MASK QLatin1String("printer-type-mask")
0041 #define KCUPS_PRINTER_COMMANDS QLatin1String("printer-commands")
0042 #define KCUPS_PRINTER_URI_SUPPORTED QLatin1String("printer-uri-supported")
0043 #define KCUPS_PRINTER_ERROR_POLICY QLatin1String("printer-error-policy")
0044 #define KCUPS_PRINTER_ERROR_POLICY_SUPPORTED QLatin1String("printer-error-policy-supported")
0045 #define KCUPS_PRINTER_OP_POLICY QLatin1String("printer-op-policy")
0046 #define KCUPS_PRINTER_OP_POLICY_SUPPORTED QLatin1String("printer-op-policy-supported")
0047 
0048 #define KCUPS_MEMBER_URIS QLatin1String("member-uris")
0049 #define KCUPS_MEMBER_NAMES QLatin1String("member-names")
0050 
0051 #define KCUPS_MARKER_CHANGE_TIME QLatin1String("marker-change-time")
0052 #define KCUPS_MARKER_COLORS QLatin1String("marker-colors")
0053 #define KCUPS_MARKER_LEVELS QLatin1String("marker-levels")
0054 #define KCUPS_MARKER_HIGH_LEVELS "marker-high-levels"
0055 #define KCUPS_MARKER_LOW_LEVELS "marker-low-levels"
0056 #define KCUPS_MARKER_NAMES QLatin1String("marker-names")
0057 #define KCUPS_MARKER_TYPES QLatin1String("marker-types")
0058 #define KCUPS_MARKER_MESSAGE "marker-message"
0059 
0060 #define KCUPS_JOB_ID QLatin1String("job-id")
0061 #define KCUPS_JOB_NAME QLatin1String("job-name")
0062 #define KCUPS_JOB_K_OCTETS QLatin1String("job-k-octets")
0063 #define KCUPS_JOB_K_OCTETS_PROCESSED QLatin1String("job-k-octets-processed")
0064 #define KCUPS_JOB_PRINTER_URI QLatin1String("job-printer-uri")
0065 #define KCUPS_JOB_PRINTER_STATE_MESSAGE QLatin1String("job-printer-state-message")
0066 #define KCUPS_JOB_ORIGINATING_USER_NAME QLatin1String("job-originating-user-name")
0067 #define KCUPS_JOB_ORIGINATING_HOST_NAME QLatin1String("job-originating-host-name")
0068 #define KCUPS_JOB_MEDIA_PROGRESS QLatin1String("job-media-progress")
0069 #define KCUPS_JOB_MEDIA_SHEETS QLatin1String("job-media-sheets")
0070 #define KCUPS_JOB_MEDIA_SHEETS_COMPLETED QLatin1String("job-media-sheets-completed")
0071 #define KCUPS_JOB_PRESERVED QLatin1String("job-preserved")
0072 #define KCUPS_JOB_STATE QLatin1String("job-state")
0073 #define KCUPS_JOB_STATE_REASONS QLatin1String("job-state-reasons")
0074 #define KCUPS_JOB_HOLD_UNTIL QLatin1String("job-hold-until")
0075 #define KCUPS_JOB_SHEETS_DEFAULT QLatin1String("job-sheets-default")
0076 #define KCUPS_JOB_SHEETS_SUPPORTED QLatin1String("job-sheets-supported")
0077 #define KCUPS_JOB_SHEETS_DEFAULT QLatin1String("job-sheets-default")
0078 #define KCUPS_JOB_SHEETS_SUPPORTED QLatin1String("job-sheets-supported")
0079 
0080 #define KCUPS_MY_JOBS QLatin1String("my-jobs")
0081 #define KCUPS_WHICH_JOBS QLatin1String("which-jobs")
0082 
0083 #define KCUPS_TIME_AT_COMPLETED QLatin1String("time-at-completed")
0084 #define KCUPS_TIME_AT_CREATION QLatin1String("time-at-creation")
0085 #define KCUPS_TIME_AT_PROCESSING QLatin1String("time-at-processing")
0086 
0087 #define KCUPS_REQUESTED_ATTRIBUTES QLatin1String("requested-attributes")
0088 
0089 #define KCUPS_REQUESTING_USER_NAME QLatin1String("requesting-user-name")
0090 #define KCUPS_REQUESTING_USER_NAME_ALLOWED QLatin1String("requesting-user-name-allowed")
0091 #define KCUPS_REQUESTING_USER_NAME_DENIED QLatin1String("requesting-user-name-denied")
0092 
0093 #define KCUPS_PPD_MAKE_AND_MODEL QLatin1String("ppd-make-and-model")
0094 
0095 #define KCUPS_NOTIFY_EVENTS QLatin1String("notify-events")
0096 #define KCUPS_NOTIFY_PULL_METHOD QLatin1String("notify-pull-method")
0097 #define KCUPS_NOTIFY_RECIPIENT_URI QLatin1String("notify-recipient-uri")
0098 #define KCUPS_NOTIFY_LEASE_DURATION QLatin1String("notify-lease-duration")
0099 #define KCUPS_NOTIFY_SUBSCRIPTION_ID QLatin1String("notify-subscription-id")
0100 
0101 #define KCUPS_AUTH_INFO QLatin1String("auth-info")
0102 #define KCUPS_AUTH_INFO_REQUIRED QLatin1String("auth-info-required")
0103 
0104 typedef QList<QVariantMap> ReturnArguments;
0105 
0106 class KIppRequest;
0107 class KCupsPasswordDialog;
0108 class KCUPSLIB_EXPORT KCupsConnection : public QThread
0109 {
0110     Q_OBJECT
0111 public:
0112     /**
0113      * This is the main Cups class @author Daniel Nicoletti <dantti12@gmail.com>
0114      *
0115      * By calling KCupsConnection::global() you have access to it.
0116      * Due to cups architecture, this class has to live on a
0117      * separate thread so we avoid blocking the user interface when
0118      * the cups call blocks.
0119      *
0120      * It is IMPORTANT that we do not create several thread
0121      * for each cups request, doing so is a valid but breaks our
0122      * authentication. We could tho store the user information an
0123      * set the user/password every time it was needed. But I am not
0124      * sure this is safe.
0125      *
0126      * Extending this means either adding methods to the KCupsRequest
0127      * class which will move to this thread and then run.
0128      */
0129     static KCupsConnection *global();
0130 
0131     /**
0132      * @brief KCupsConnection
0133      * @param parent
0134      *
0135      * This is the default constructor that connects to the default server
0136      * If you don't have any special reason for creating a connection
0137      * on your own consider calling global()
0138      */
0139     explicit KCupsConnection(QObject *parent = nullptr);
0140     explicit KCupsConnection(const QUrl &server, QObject *parent = nullptr);
0141     ~KCupsConnection() override;
0142 
0143     void setPasswordMainWindow(WId mainwindow);
0144 
0145 Q_SIGNALS:
0146     /**
0147      * emitted when "server-started" is registered
0148      */
0149     void serverStarted(const QString &text);
0150 
0151     /**
0152      * emitted when "server-stopped" is registered
0153      */
0154     void serverStopped(const QString &text);
0155 
0156     /**
0157      * emitted when "server-restarted" is registered
0158      */
0159     void serverRestarted(const QString &text);
0160 
0161     /**
0162      * emitted when "server-audit" is registered
0163      */
0164     void serverAudit(const QString &text);
0165 
0166     /**
0167      * emitted when "printer-added" is registered
0168      */
0169     void printerAdded(const QString &text,
0170                       const QString &printerUri,
0171                       const QString &printerName,
0172                       uint printerState,
0173                       const QString &printerStateReasons,
0174                       bool printerIsAcceptingJobs);
0175 
0176     /**
0177      * emitted when "printer-modified" is registered
0178      */
0179     void printerModified(const QString &text,
0180                          const QString &printerUri,
0181                          const QString &printerName,
0182                          uint printerState,
0183                          const QString &printerStateReasons,
0184                          bool printerIsAcceptingJobs);
0185 
0186     /**
0187      * emitted when "printer-deleted" is registered
0188      */
0189     void printerDeleted(const QString &text,
0190                         const QString &printerUri,
0191                         const QString &printerName,
0192                         uint printerState,
0193                         const QString &printerStateReasons,
0194                         bool printerIsAcceptingJobs);
0195 
0196     /**
0197      * emitted when "printer-state-changed" is registered
0198      */
0199     void printerStateChanged(const QString &text,
0200                              const QString &printerUri,
0201                              const QString &printerName,
0202                              uint printerState,
0203                              const QString &printerStateReasons,
0204                              bool printerIsAcceptingJobs);
0205 
0206     /**
0207      * emitted when "printer-stopped" is registered
0208      */
0209     void printerStopped(const QString &text,
0210                         const QString &printerUri,
0211                         const QString &printerName,
0212                         uint printerState,
0213                         const QString &printerStateReasons,
0214                         bool printerIsAcceptingJobs);
0215 
0216     /**
0217      * emitted when "printer-restarted" is registered
0218      */
0219     void printerRestarted(const QString &text,
0220                           const QString &printerUri,
0221                           const QString &printerName,
0222                           uint printerState,
0223                           const QString &printerStateReasons,
0224                           bool printerIsAcceptingJobs);
0225 
0226     /**
0227      * emitted when "printer-shutdown" is registered
0228      */
0229     void printerShutdown(const QString &text,
0230                          const QString &printerUri,
0231                          const QString &printerName,
0232                          uint printerState,
0233                          const QString &printerStateReasons,
0234                          bool printerIsAcceptingJobs);
0235 
0236     /**
0237      * emitted when "printer-media-changed" is registered
0238      */
0239     void printerMediaChanged(const QString &text,
0240                              const QString &printerUri,
0241                              const QString &printerName,
0242                              uint printerState,
0243                              const QString &printerStateReasons,
0244                              bool printerIsAcceptingJobs);
0245 
0246     /**
0247      * emitted when "printer-finishings-changed" is registered
0248      */
0249     void printerFinishingsChanged(const QString &text,
0250                                   const QString &printerUri,
0251                                   const QString &printerName,
0252                                   uint printerState,
0253                                   const QString &printerStateReasons,
0254                                   bool printerIsAcceptingJobs);
0255 
0256     /**
0257      * emitted when "job-state-changed" is registered
0258      */
0259     void jobState(const QString &text,
0260                   const QString &printerUri,
0261                   const QString &printerName,
0262                   uint printerState,
0263                   const QString &printerStateReasons,
0264                   bool printerIsAcceptingJobs,
0265                   uint jobId,
0266                   uint jobState,
0267                   const QString &jobStateReasons,
0268                   const QString &jobName,
0269                   uint jobImpressionsCompleted);
0270 
0271     /**
0272      * emitted when "job-created" is registered
0273      */
0274     void jobCreated(const QString &text,
0275                     const QString &printerUri,
0276                     const QString &printerName,
0277                     uint printerState,
0278                     const QString &printerStateReasons,
0279                     bool printerIsAcceptingJobs,
0280                     uint jobId,
0281                     uint jobState,
0282                     const QString &jobStateReasons,
0283                     const QString &jobName,
0284                     uint jobImpressionsCompleted);
0285 
0286     /**
0287      * emitted when "job-stopped" is registered
0288      */
0289     void jobStopped(const QString &text,
0290                     const QString &printerUri,
0291                     const QString &printerName,
0292                     uint printerState,
0293                     const QString &printerStateReasons,
0294                     bool printerIsAcceptingJobs,
0295                     uint jobId,
0296                     uint jobState,
0297                     const QString &jobStateReasons,
0298                     const QString &jobName,
0299                     uint jobImpressionsCompleted);
0300 
0301     /**
0302      * emitted when "job-config-changed" is registered
0303      */
0304     void jobConfigChanged(const QString &text,
0305                           const QString &printerUri,
0306                           const QString &printerName,
0307                           uint printerState,
0308                           const QString &printerStateReasons,
0309                           bool printerIsAcceptingJobs,
0310                           uint jobId,
0311                           uint jobState,
0312                           const QString &jobStateReasons,
0313                           const QString &jobName,
0314                           uint jobImpressionsCompleted);
0315 
0316     /**
0317      * emitted when "job-progress" is registered
0318      */
0319     void jobProgress(const QString &text,
0320                      const QString &printerUri,
0321                      const QString &printerName,
0322                      uint printerState,
0323                      const QString &printerStateReasons,
0324                      bool printerIsAcceptingJobs,
0325                      uint jobId,
0326                      uint jobState,
0327                      const QString &jobStateReasons,
0328                      const QString &jobName,
0329                      uint jobImpressionsCompleted);
0330 
0331     /**
0332      * emitted when "job-completed" is registered
0333      */
0334     void jobCompleted(const QString &text,
0335                       const QString &printerUri,
0336                       const QString &printerName,
0337                       uint printerState,
0338                       const QString &printerStateReasons,
0339                       bool printerIsAcceptingJobs,
0340                       uint jobId,
0341                       uint jobState,
0342                       const QString &jobStateReasons,
0343                       const QString &jobName,
0344                       uint jobImpressionsCompleted);
0345 
0346     void rhPrinterAdded(const QString &queueName);
0347     void rhPrinterRemoved(const QString &queueName);
0348     void rhQueueChanged(const QString &queueName);
0349     void rhJobQueuedLocal(const QString &queueName, uint jobId, const QString &jobOwner);
0350     void rhJobStartedLocal(const QString &queueName, uint jobId, const QString &jobOwner);
0351 
0352 protected:
0353     friend class KCupsRequest;
0354 
0355     virtual void run() override;
0356     bool readyToStart();
0357     bool retry(const char *resource, int operation) const;
0358     ReturnArguments request(const KIppRequest &request, ipp_tag_t groupTag = IPP_TAG_ZERO) const;
0359 
0360 private slots:
0361     void updateSubscription();
0362     void renewDBusSubscription();
0363     void cancelDBusSubscription();
0364 
0365 protected:
0366     virtual void connectNotify(const QMetaMethod &signal) override;
0367     virtual void disconnectNotify(const QMetaMethod &signal) override;
0368     QString eventForSignal(const QMetaMethod &signal) const;
0369 
0370 private:
0371     void init();
0372 
0373     int renewDBusSubscription(int subscriptionId, int leaseDuration, const QStringList &events = QStringList());
0374 
0375     void notifierConnect(const QString &signal, QObject *receiver, const char *slot);
0376 
0377     static ReturnArguments parseIPPVars(ipp_t *response, ipp_tag_t group_tag);
0378     static QVariant ippAttrToVariant(ipp_attribute_t *attr);
0379 
0380     static KCupsConnection *m_instance;
0381 
0382     bool m_inited = false;
0383     KCupsPasswordDialog *m_passwordDialog;
0384     QUrl m_serverUrl;
0385 
0386     QTimer *m_subscriptionTimer;
0387     QTimer *m_renewTimer;
0388     QStringList m_connectedEvents; // note this updated in another thread. Always guard with m_mutex
0389     QStringList m_requestedDBusEvents;
0390     int m_subscriptionId = -1;
0391     QMutex m_mutex;
0392 };
0393 
0394 #endif // KCUPSCONNECTION_H