File indexing completed on 2024-04-14 05:39:32

0001 // This license reflects the original Adept code:
0002 // -*- C++ -*- (c) 2008 Petr Rockai <me@mornfall.net>
0003 //             (c) 2011 Modestas Vainius <modax@debian.org>
0004 // Redistribution and use in source and binary forms, with or without
0005 // modification, are permitted provided that the following conditions are
0006 // met:
0007 //
0008 //     * Redistributions of source code must retain the above copyright
0009 //       notice, this list of conditions and the following disclaimer.
0010 //
0011 //     * Redistributions in binary form must reproduce the above
0012 //       copyright notice, this list of conditions and the following
0013 //       disclaimer in the documentation and/or other materials provided
0014 //       with the distribution.
0015 //
0016 //     * Neither the name of [original copyright holder] nor the names of
0017 //       its contributors may be used to endorse or promote products
0018 //       derived from this software without specific prior written
0019 //       permission.
0020 //
0021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0022 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0023 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0024 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0025 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0027 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0028 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0029 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0030 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0031 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0032 /*
0033  * All the modifications below are licensed under this license
0034  * Copyright (C) 2010 Daniel Nicoletti <dantti12@gmail.com>
0035  *
0036  * This library is free software; you can redistribute it and/or
0037  * modify it under the terms of the GNU Library General Public
0038  * License as published by the Free Software Foundation; either
0039  * version 2 of the License, or (at your option) any later version.
0040  *
0041  * This library is distributed in the hope that it will be useful,
0042  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0043  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0044  * Library General Public License for more details.
0045  *
0046  * You should have received a copy of the GNU Library General Public License
0047  * along with this library; see the file COPYING.LIB. If not, write to
0048  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0049  * Boston, MA 02110-1301, USA.
0050  */
0051 
0052 #ifndef DEBCONF_H
0053 #define DEBCONF_H
0054 
0055 #include <QtCore/QHash>
0056 #include <QtCore/QStringList>
0057 #include <QtCore/QMetaEnum>
0058 #include <QtCore/QMetaObject>
0059 #include <QtCore/QFile>
0060 #include <QtNetwork/QLocalSocket>
0061 #include <QtNetwork/QLocalServer>
0062 
0063 class QSocketNotifier;
0064 
0065 namespace DebconfKde {
0066 
0067 /**
0068   * An abstract class which talks Debconf Passthrough frontend protocol. It
0069   * does not implement underlying I/O method specifics.
0070   */
0071 class DebconfFrontend : public QObject {
0072     Q_OBJECT
0073     Q_ENUMS(PropertyKey)
0074     Q_ENUMS(TypeKey)
0075 public:
0076     typedef enum {
0077         Choices,
0078         Description,
0079         ExtendedDescription,
0080         Type,
0081         UnknownPropertyKey = -1
0082     } PropertyKey;
0083 
0084     typedef enum {
0085         String,
0086         Password,
0087         Progress,
0088         Boolean,
0089         Select,
0090         Multiselect,
0091         Note,
0092         Error,
0093         Title,
0094         Text,
0095         UnknownTypeKey = -1
0096     } TypeKey;
0097 
0098     explicit DebconfFrontend(QObject *parent = 0);
0099     virtual ~DebconfFrontend();
0100 
0101     QString value(const QString &key) const;
0102     void setValue(const QString &key, const QString &value);
0103 
0104     QString property(const QString &key, PropertyKey p) const;
0105 
0106     TypeKey type(const QString &string) const;
0107 
0108     /**
0109       * Send \p string to Debconf over established connection
0110       */
0111     void say(const QString &string);
0112 
0113     /**
0114      * Goes to the next question
0115      */
0116     void next();
0117     /**
0118      * Goes back one question (if backup(true) was emitted)
0119      */
0120     void back();
0121     /**
0122      * Closes the current connection, canceling all questions
0123      */
0124     virtual void cancel();
0125 
0126 Q_SIGNALS:
0127     void go(const QString &title, const QStringList &input);
0128     void progress(const QString &param);
0129     /**
0130       * Emitted when connection with Debconf is terminated.
0131       */
0132     void finished();
0133     void backup(bool capable);
0134 
0135 protected Q_SLOTS:
0136     /**
0137      * This slot should be called when there is new data available.
0138      */
0139     virtual bool process();
0140 
0141     /**
0142      * This slot should be called when connection with Debconf is terminated.
0143      */
0144     virtual void disconnected();
0145 
0146 protected:
0147     /**
0148       * This method must be overridden by the derivative class and return
0149       * current QIODevice which should be used to read data from Debconf.
0150       */
0151     virtual QIODevice* getReadDevice() const = 0;
0152     /**
0153       * This method must be overridden by the derivative class and return
0154       * current QIODevice which should be used to write data to Debconf.
0155       */
0156     virtual QIODevice* getWriteDevice() const = 0;
0157     /**
0158      * This is called to clean up internal data once connection with
0159      * Debconf is terminated.
0160      */
0161     virtual void reset();
0162 
0163 private:
0164     void cmd_capb(const QString &caps);
0165     void cmd_set(const QString &param);
0166     void cmd_get(const QString &param);
0167     void cmd_input(const QString &param);
0168     void cmd_go(const QString &);
0169     void cmd_title(const QString &param);
0170     void cmd_data(const QString &param);
0171     void cmd_subst(const QString &param);
0172     void cmd_progress(const QString &param);
0173     void cmd_x_ping(const QString &param);
0174     void cmd_version(const QString &param);
0175     void cmd_x_loadtemplatefile(const QString &param);
0176     void cmd_info(const QString &param);
0177     void cmd_fget(const QString &param);
0178     void cmd_fset(const QString &param);
0179     void cmd_beginblock(const QString &param);
0180     void cmd_endblock(const QString &param);
0181     void cmd_stop(const QString &param);
0182     struct Cmd {
0183         const char *cmd;
0184         void (DebconfFrontend::*run)(const QString &);
0185     };
0186     static const Cmd commands[];
0187 
0188     // TODO this is apparently very much untested
0189     QString substitute(const QString &key, const QString &rest) const;
0190     /**
0191      * Transforms the string camel cased and return it's enum given the enum name
0192      */
0193     template<class T> static int enumFromString(const QString &str, const char *enumName);
0194     PropertyKey propertyKeyFromString(const QString &string);
0195 
0196     typedef QHash<PropertyKey, QString> Properties;
0197     typedef QHash<QString, QString> Substitutions;
0198     typedef QHash<QString, bool> Flags;
0199 
0200     QHash<QString, Properties>    m_data;
0201     QHash<QString, Substitutions> m_subst;
0202     QHash<QString, QString>       m_values;
0203     QHash<QString, Flags>         m_flags;
0204     QString m_title;
0205     QStringList m_input;
0206 };
0207 
0208 /**
0209   * DebconfFrontend which communicates with Debconf over UNIX socket. Even when
0210   * finished signal is emitted, DeconfFrontend will reset and continue to
0211   * listen for new connections on the socket.
0212   */
0213 class DebconfFrontendSocket : public DebconfFrontend {
0214     Q_OBJECT
0215 
0216 public:
0217     /**
0218       * Instantiates the class and starts listening for new connections on the
0219       * socket at \p socketName path. Please note that any file at \p socketName
0220       * will be removed if it exists prior to the call of this constructor.
0221       */
0222     explicit DebconfFrontendSocket(const QString &socketName, QObject *parent = 0);
0223 
0224     /**
0225       * Removes socket when the object is destroyed.
0226       */
0227     virtual ~DebconfFrontendSocket();
0228 
0229     /**
0230       * Overridden to trigger termination of the current connection.
0231       */
0232     void cancel() override;
0233 
0234 protected:
0235     inline QIODevice* getReadDevice() const override { return m_socket; }
0236     inline QIODevice* getWriteDevice() const override { return m_socket; }
0237     void reset() override;
0238 
0239 private Q_SLOTS:
0240     /**
0241      * Called when a new connection is received on the socket
0242      * If we are already handlyng a connection we refuse the others
0243      */
0244     void newConnection();
0245 
0246 private:
0247     QLocalServer *m_server;
0248     QLocalSocket *m_socket;
0249 };
0250 
0251 /**
0252   * DebconfFrontend which communicates with Debconf over FIFO pipes. Once
0253   * finished signal is emitted, the frontend is no longer usable as pipes
0254   * have been been closed by then.
0255   */
0256 class DebconfFrontendFifo : public DebconfFrontend {
0257 
0258 public:
0259     /**
0260       * Instantiates the class and prepares for communication with Debconf over
0261       * \p readfd (read) and \p writefd (write) FIFO file descriptors.
0262       */
0263     explicit DebconfFrontendFifo(int readfd, int writefd, QObject *parent = 0);
0264 
0265     /**
0266       * Overridden to trigger full disconnection
0267       */
0268     void cancel() override;
0269 
0270 protected:
0271     QIODevice* getReadDevice() const override { return m_readf; }
0272     QIODevice* getWriteDevice() const override { return m_writef; }
0273     void reset() override;
0274     bool process() override;
0275 
0276 private:
0277     QFile *m_readf;
0278     QFile *m_writef;
0279     QSocketNotifier *m_readnotifier;
0280 };
0281 
0282 }
0283 
0284 #endif