]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - liblightdm-qt/greeter.cpp
Load all users only when really needed
[sojka/lightdm.git] / liblightdm-qt / greeter.cpp
index 5b3a264a80641878dd5c6875f734e1fdbac32162..d535a02222153752947a740243ac454a6a04dde9 100644 (file)
  *
  * This library is free software; you can redistribute it and/or modify it under
  * the terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at your option) any
- * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
- * license.
+ * Software Foundation; either version 2 or version 3 of the License.
+ * See http://www.gnu.org/copyleft/lgpl.html the full text of the license.
  */
 
-#include "config.h"
 
-#include "QLightDM/Greeter"
-#include "QLightDM/User"
-#include "QLightDM/SessionsModel"
+#include "QLightDM/greeter.h"
 
-#include <security/pam_appl.h>
-
-#include <QtNetwork/QHostInfo> //needed for localHostName
 #include <QtCore/QDebug>
 #include <QtCore/QDir>
 #include <QtCore/QVariant>
 #include <QtCore/QSettings>
-#include <QtCore/QUrl>
-#include <QtCore/QFile>
-#include <QtCore/QHash>
-#include <QtCore/QSocketNotifier>
-#include <QtDBus/QDBusPendingReply>
-#include <QtDBus/QDBusInterface>
-#include <QtDBus/QDBusReply>
-
-/* Messages from the greeter to the server */
-typedef enum
-{
-    GREETER_MESSAGE_CONNECT = 0,
-    GREETER_MESSAGE_AUTHENTICATE,
-    GREETER_MESSAGE_AUTHENTICATE_AS_GUEST,
-    GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
-    GREETER_MESSAGE_START_SESSION,
-    GREETER_MESSAGE_CANCEL_AUTHENTICATION
-} GreeterMessage;
-
-/* Messages from the server to the greeter */
-typedef enum
-{
-    SERVER_MESSAGE_CONNECTED = 0,
-    SERVER_MESSAGE_QUIT,
-    SERVER_MESSAGE_PROMPT_AUTHENTICATION,
-    SERVER_MESSAGE_END_AUTHENTICATION,
-    SERVER_MESSAGE_SESSION_FAILED,
-} ServerMessage;
-
-#define HEADER_SIZE 8
+
+#include <lightdm.h>
 
 using namespace QLightDM;
 
-class GreeterPrivate
+class QLightDM::GreeterPrivate
 {
 public:
-    SessionsModel *sessionsModel;
-
-    QHash<QString, QString> hints;
-
-    int toServerFd;
-    int fromServerFd;
-    QSocketNotifier *n;
-    char *readBuffer;
-    int nRead;
-    bool inAuthentication;
-    bool isAuthenticated;
-    QString authenticationUser;
-    int authenticateSequenceNumber;
-    bool cancellingAuthentication;
+    GreeterPrivate(Greeter *parent);
+    LightDMGreeter *ldmGreeter;
+protected:
+    Greeter* q_ptr;
+
+    static void cb_showPrompt(LightDMGreeter *greeter, const gchar *text, LightDMPromptType type, gpointer data);
+    static void cb_showMessage(LightDMGreeter *greeter, const gchar *text, LightDMMessageType type, gpointer data);
+    static void cb_authenticationComplete(LightDMGreeter *greeter, gpointer data);
+    static void cb_autoLoginExpired(LightDMGreeter *greeter, gpointer data);
+    static void cb_idle(LightDMGreeter *greeter, gpointer data);
+    static void cb_reset(LightDMGreeter *greeter, gpointer data);
+
+private:
+    Q_DECLARE_PUBLIC(Greeter)
 };
 
-
-Greeter::Greeter(QObject *parent) :
-    QObject(parent),
-    d(new GreeterPrivate)
+GreeterPrivate::GreeterPrivate(Greeter *parent) :
+    q_ptr(parent)
 {
-    d->readBuffer = (char *)malloc (HEADER_SIZE);
-    d->nRead = 0;
-    d->sessionsModel = new SessionsModel(this);
-    d->authenticateSequenceNumber = 0;
+#if !defined(GLIB_VERSION_2_36)
+    g_type_init();
+#endif
+    ldmGreeter = lightdm_greeter_new();
+
+    g_signal_connect (ldmGreeter, LIGHTDM_GREETER_SIGNAL_SHOW_PROMPT, G_CALLBACK (cb_showPrompt), this);
+    g_signal_connect (ldmGreeter, LIGHTDM_GREETER_SIGNAL_SHOW_MESSAGE, G_CALLBACK (cb_showMessage), this);
+    g_signal_connect (ldmGreeter, LIGHTDM_GREETER_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (cb_authenticationComplete), this);
+    g_signal_connect (ldmGreeter, LIGHTDM_GREETER_SIGNAL_AUTOLOGIN_TIMER_EXPIRED, G_CALLBACK (cb_autoLoginExpired), this);
+    g_signal_connect (ldmGreeter, LIGHTDM_GREETER_SIGNAL_IDLE, G_CALLBACK (cb_idle), this);
+    g_signal_connect (ldmGreeter, LIGHTDM_GREETER_SIGNAL_RESET, G_CALLBACK (cb_reset), this);
 }
 
-Greeter::~Greeter()
+void GreeterPrivate::cb_showPrompt(LightDMGreeter *greeter, const gchar *text, LightDMPromptType type, gpointer data)
 {
-    delete d->readBuffer;
-    delete d;
+    Q_UNUSED(greeter);
+
+    GreeterPrivate *that = static_cast<GreeterPrivate*>(data);
+    QString message = QString::fromUtf8(text);
+
+    Q_EMIT that->q_func()->showPrompt(message, type == LIGHTDM_PROMPT_TYPE_QUESTION ?
+                                               Greeter::PromptTypeQuestion : Greeter::PromptTypeSecret);
 }
 
-static int intLength()
+void GreeterPrivate::cb_showMessage(LightDMGreeter *greeter, const gchar *text, LightDMMessageType type, gpointer data)
 {
-    return 4;
+    Q_UNUSED(greeter);
+
+    GreeterPrivate *that = static_cast<GreeterPrivate*>(data);
+    QString message = QString::fromUtf8(text);
+
+    Q_EMIT that->q_func()->showMessage(message, type == LIGHTDM_MESSAGE_TYPE_INFO ?
+                                                Greeter::MessageTypeInfo : Greeter::MessageTypeError);
 }
 
-static int stringLength(QString value)
+void GreeterPrivate::cb_authenticationComplete(LightDMGreeter *greeter, gpointer data)
 {
-    QByteArray a = value.toUtf8();
-    return intLength() + a.size();
+    Q_UNUSED(greeter);
+    GreeterPrivate *that = static_cast<GreeterPrivate*>(data);
+    Q_EMIT that->q_func()->authenticationComplete();
 }
 
-void Greeter::writeInt(int value)
+void GreeterPrivate::cb_autoLoginExpired(LightDMGreeter *greeter, gpointer data)
 {
-    char buffer[4];
-    buffer[0] = value >> 24;
-    buffer[1] = (value >> 16) & 0xFF;
-    buffer[2] = (value >> 8) & 0xFF;
-    buffer[3] = value & 0xFF;
-    if (write(d->toServerFd, buffer, intLength()) != intLength()) {
-        qDebug() << "Error writing to server";
-    }
+    Q_UNUSED(greeter);
+    GreeterPrivate *that = static_cast<GreeterPrivate*>(data);
+    Q_EMIT that->q_func()->autologinTimerExpired();
 }
 
-void Greeter::writeString(QString value)
+void GreeterPrivate::cb_idle(LightDMGreeter *greeter, gpointer data)
 {
-    QByteArray a = value.toUtf8();
-    writeInt(a.size());
-    if (write(d->toServerFd, a.data(), a.size()) != a.size()) {
-        qDebug() << "Error writing to server";
-    }
+    Q_UNUSED(greeter);
+    GreeterPrivate *that = static_cast<GreeterPrivate*>(data);
+    Q_EMIT that->q_func()->idle();
 }
 
-void Greeter::writeHeader(int id, int length)
+void GreeterPrivate::cb_reset(LightDMGreeter *greeter, gpointer data)
 {
-    writeInt(id);
-    writeInt(length);
+    Q_UNUSED(greeter);
+    GreeterPrivate *that = static_cast<GreeterPrivate*>(data);
+    Q_EMIT that->q_func()->reset();
 }
 
-void Greeter::flush()
+Greeter::Greeter(QObject *parent) :
+    QObject(parent),
+    d_ptr(new GreeterPrivate(this))
 {
-    fsync(d->toServerFd);
 }
 
-int Greeter::getPacketLength()
+Greeter::~Greeter()
 {
-    int offset = intLength();
-    return readInt(&offset);
+    delete d_ptr;
 }
 
-int Greeter::readInt(int *offset)
-{
-    if(d->nRead - *offset < intLength()) {
-        qDebug() << "Not enough space for int, need " << intLength() << ", got " << (d->nRead - *offset);
-        return 0;
-    }
 
-    char *buffer = d->readBuffer + *offset;
-    int value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
-    *offset += intLength();
-    return value;
+bool Greeter::connectToDaemonSync()
+{
+    Q_D(Greeter);
+    return lightdm_greeter_connect_to_daemon_sync(d->ldmGreeter, NULL);
 }
 
-QString Greeter::readString(int *offset)
+bool Greeter::connectSync()
 {
-    int length = readInt(offset);
-    if(d->nRead - *offset < length) {
-        qDebug() << "Not enough space for string, need " << length << ", got " << (d->nRead - *offset);
-        return "";
-    }
-    char *start = d->readBuffer + *offset;
-    *offset += length;
-    return QString::fromUtf8(start, length);
+    Q_D(Greeter);
+    return lightdm_greeter_connect_to_daemon_sync(d->ldmGreeter, NULL);
 }
 
-void Greeter::connectToServer()
+void Greeter::authenticate(const QString &username)
 {
-    QDBusConnection busType = QDBusConnection::systemBus();
-    QString ldmBus(qgetenv("LIGHTDM_BUS"));
-    if(ldmBus == QLatin1String("SESSION")) {
-        busType = QDBusConnection::sessionBus();
-    }
-
-    char* fd = getenv("LIGHTDM_TO_SERVER_FD");
-    if(!fd) {
-       qDebug() << "No LIGHTDM_TO_SERVER_FD environment variable";
-       return;
-    }
-    d->toServerFd = atoi(fd);
-
-    qDebug() << "***connecting to server";
-    QFile toServer;
-    qDebug() << toServer.open(d->toServerFd, QIODevice::WriteOnly);
-
-    fd = getenv("LIGHTDM_FROM_SERVER_FD");
-    if(!fd) {
-       qDebug() << "No LIGHTDM_FROM_SERVER_FD environment variable";
-       return;
-    }
-    d->fromServerFd = atoi(fd);
-
-    d->n = new QSocketNotifier(d->fromServerFd, QSocketNotifier::Read);
-    connect(d->n, SIGNAL(activated(int)), this, SLOT(onRead(int)));
+    Q_D(Greeter);
+    lightdm_greeter_authenticate(d->ldmGreeter, username.toLocal8Bit().data(), NULL);
+}
 
-    qDebug() << "Connecting to display manager...";
-    writeHeader(GREETER_MESSAGE_CONNECT, stringLength(VERSION));
-    writeString(VERSION);
-    flush();
+void Greeter::authenticateAsGuest()
+{
+    Q_D(Greeter);
+    lightdm_greeter_authenticate_as_guest(d->ldmGreeter, NULL);
 }
 
-void Greeter::authenticate(const QString &username)
+void Greeter::authenticateAutologin()
 {
-    d->inAuthentication = true;
-    d->isAuthenticated = false;
-    d->cancellingAuthentication = false;
-    d->authenticationUser = username;
-    qDebug() << "Starting authentication for user " << username << "...";
-    writeHeader(GREETER_MESSAGE_AUTHENTICATE, intLength() + stringLength(username));
-    d->authenticateSequenceNumber++;
-    writeInt(d->authenticateSequenceNumber);
-    writeString(username);
-    flush();
+    Q_D(Greeter);
+    lightdm_greeter_authenticate_autologin(d->ldmGreeter, NULL);
 }
 
-void Greeter::authenticateAsGuest()
+void Greeter::authenticateRemote(const QString &session, const QString &username)
 {
-    d->authenticateSequenceNumber++;
-    d->inAuthentication = true;
-    d->isAuthenticated = false;
-    d->cancellingAuthentication = false;
-    d->authenticationUser = "";
-    qDebug() << "Starting authentication for guest account";
-    writeHeader(GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, intLength());
-    writeInt(d->authenticateSequenceNumber);
-    flush();
+    Q_D(Greeter);
+    lightdm_greeter_authenticate_remote(d->ldmGreeter, session.toLocal8Bit().data(), username.toLocal8Bit().data(), NULL);
 }
 
 void Greeter::respond(const QString &response)
 {
-    qDebug() << "Providing response to display manager";
-    writeHeader(GREETER_MESSAGE_CONTINUE_AUTHENTICATION, intLength() + stringLength(response));
-    // FIXME: Could be multiple response required
-    writeInt(1);
-    writeString(response);
-    flush();
+    Q_D(Greeter);
+    lightdm_greeter_respond(d->ldmGreeter, response.toLocal8Bit().data(), NULL);
 }
 
 void Greeter::cancelAuthentication()
 {
-    qDebug() << "Cancelling authentication";
-    d->cancellingAuthentication = true;
-    writeHeader(GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0);
-    flush();
+    Q_D(Greeter);
+    lightdm_greeter_cancel_authentication(d->ldmGreeter, NULL);
+}
+
+void Greeter::cancelAutologin()
+{
+    Q_D(Greeter);
+    lightdm_greeter_cancel_autologin(d->ldmGreeter);
 }
 
 bool Greeter::inAuthentication() const
 {
-    return d->inAuthentication;
+    Q_D(const Greeter);
+    return lightdm_greeter_get_in_authentication(d->ldmGreeter);
 }
 
 bool Greeter::isAuthenticated() const
 {
-    return d->isAuthenticated;
+    Q_D(const Greeter);
+    return lightdm_greeter_get_is_authenticated(d->ldmGreeter);
 }
 
 QString Greeter::authenticationUser() const
 {
-    return d->authenticationUser;
-}
-
-void Greeter::startSession(const QString &session)
-{
-    qDebug() << "Starting session " << session;
-    writeHeader(GREETER_MESSAGE_START_SESSION, stringLength(session));
-    writeString(session);
-    flush();
-}
-
-void Greeter::onRead(int fd)
-{
-    //qDebug() << "Reading from server";
-
-    int nToRead = HEADER_SIZE;
-    if(d->nRead >= HEADER_SIZE)
-        nToRead += getPacketLength();
-
-    ssize_t nRead;
-    nRead = read(fd, d->readBuffer + d->nRead, nToRead - d->nRead);
-    if(nRead < 0)
-    {
-        qDebug() << "Error reading from server";
-        return;
-    }
-    if (nRead == 0)
-    {
-        qDebug() << "EOF reading from server";
-        return;
-    }
-
-    //qDebug() << "Read " << nRead << "octets";
-    d->nRead += nRead;
-    if(d->nRead != nToRead)
-        return;
-
-    /* If have header, rerun for content */
-    if(d->nRead == HEADER_SIZE)
-    {
-        nToRead = getPacketLength();
-        if(nToRead > 0)
-        {
-            d->readBuffer = (char *)realloc(d->readBuffer, HEADER_SIZE + nToRead);
-            onRead(fd);
-            return;
-        }
-    }
-
-    int offset = 0;
-    int id = readInt(&offset);
-    int length = readInt(&offset);
-    int nMessages, sequenceNumber, returnCode;
-    QString version, username;
-    QString hintString = "";
-    switch(id)
-    {
-    case SERVER_MESSAGE_CONNECTED:
-        version = readString(&offset);
-        while (offset < length)
-        {
-            QString name = readString(&offset);
-            QString value = readString(&offset);
-            hintString.append (" ");
-            hintString.append (name);
-            hintString.append ("=");
-            hintString.append (value);
-        }
-
-        qDebug() << "Connected version=" << version << hintString;
-
-        emit connected();
-        break;
-    case SERVER_MESSAGE_QUIT:
-        qDebug() << "Got quit request from server";
-        emit quit();
-        break;
-    case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
-        sequenceNumber = readInt(&offset);
-
-        if (sequenceNumber == d->authenticateSequenceNumber &&
-            !d->cancellingAuthentication)
-        {
-            nMessages = readInt(&offset);
-            qDebug() << "Prompt user with " << nMessages << " message(s)";
-            for(int i = 0; i < nMessages; i++)
-            {
-                int msg_style = readInt (&offset);
-                QString msg = readString (&offset);
-
-                // FIXME: Should stop on prompts?
-                switch (msg_style)
-                {
-                case PAM_PROMPT_ECHO_OFF:
-                    emit showPrompt(msg, PROMPT_TYPE_SECRET);
-                    break;
-                case PAM_PROMPT_ECHO_ON:
-                    emit showPrompt(msg, PROMPT_TYPE_QUESTION);
-                    break;
-                case PAM_ERROR_MSG:
-                    emit showMessage(msg, MESSAGE_TYPE_ERROR);
-                    break;
-                case PAM_TEXT_INFO:
-                    emit showMessage(msg, MESSAGE_TYPE_INFO);
-                    break;
-                }
-            }
-        }
-        break;
-    case SERVER_MESSAGE_END_AUTHENTICATION:
-        sequenceNumber = readInt(&offset);
-        returnCode = readInt(&offset);
-
-        if (sequenceNumber == d->authenticateSequenceNumber)
-        {
-            qDebug() << "Authentication complete with return code " << returnCode;
-            d->cancellingAuthentication = false;
-            d->isAuthenticated = (returnCode == 0);
-            if(!d->isAuthenticated) {
-                d->authenticationUser = "";
-            }
-            emit authenticationComplete();
-            d->inAuthentication = false;
-        }
-        else
-            qDebug () << "Ignoring end authentication with invalid sequence number " << sequenceNumber;
-        break;
-    case SERVER_MESSAGE_SESSION_FAILED:
-        qDebug() << "Session failed to start";
-        emit sessionFailed();
-        break;
-    default:
-        qDebug() << "Unknown message from server: " << id;
-    }
-
-    d->nRead = 0;
+    Q_D(const Greeter);
+    return QString::fromUtf8(lightdm_greeter_get_authentication_user(d->ldmGreeter));
 }
 
-QString Greeter::hostname() const
+void Greeter::setLanguage (const QString &language)
+{
+    Q_D(Greeter);
+    lightdm_greeter_set_language(d->ldmGreeter, language.toLocal8Bit().constData(), NULL);
+}
+
+void Greeter::setResettable (bool resettable)
 {
-    return QHostInfo::localHostName();
+    Q_D(Greeter);
+    lightdm_greeter_set_resettable(d->ldmGreeter, resettable);
 }
 
-QString Greeter::defaultLanguage() const
+bool Greeter::startSessionSync(const QString &session)
 {
-    return getenv("LANG");
+    Q_D(Greeter);
+    return lightdm_greeter_start_session_sync(d->ldmGreeter, session.toLocal8Bit().constData(), NULL);
 }
 
-QString Greeter::getHint(QString name) const
+QString Greeter::ensureSharedDataDirSync(const QString &username)
 {
-    return d->hints.value (name);
+    Q_D(Greeter);
+    return QString::fromUtf8(lightdm_greeter_ensure_shared_data_dir_sync(d->ldmGreeter, username.toLocal8Bit().constData(), NULL));
+}
+
+
+QString Greeter::getHint(const QString &name) const
+{
+    Q_D(const Greeter);
+    return lightdm_greeter_get_hint(d->ldmGreeter, name.toLocal8Bit().constData());
 }
 
 QString Greeter::defaultSessionHint() const
 {
-    return getHint ("default-session");
+    Q_D(const Greeter);
+    return QString::fromUtf8(lightdm_greeter_get_default_session_hint(d->ldmGreeter));
 }
 
 bool Greeter::hideUsersHint() const
 {
-    return d->hints.value ("hide-users", "true") == "true";
+    Q_D(const Greeter);
+    return lightdm_greeter_get_hide_users_hint(d->ldmGreeter);
+}
+
+bool Greeter::showManualLoginHint() const
+{
+    Q_D(const Greeter);
+    return lightdm_greeter_get_show_manual_login_hint(d->ldmGreeter);
+}
+
+bool Greeter::showRemoteLoginHint() const
+{
+    Q_D(const Greeter);
+    return lightdm_greeter_get_show_remote_login_hint(d->ldmGreeter);
+}
+
+bool Greeter::lockHint() const
+{
+    Q_D(const Greeter);
+    return lightdm_greeter_get_lock_hint(d->ldmGreeter);
 }
 
 bool Greeter::hasGuestAccountHint() const
 {
-    return d->hints.value ("has-guest-account", "false") == "true";
+    Q_D(const Greeter);
+    return lightdm_greeter_get_has_guest_account_hint(d->ldmGreeter);
 }
 
 QString Greeter::selectUserHint() const
 {
-    return getHint ("select-user");
+    Q_D(const Greeter);
+    return QString::fromUtf8(lightdm_greeter_get_select_user_hint(d->ldmGreeter));
 }
 
 bool Greeter::selectGuestHint() const
 {
-    return d->hints.value ("select-guest", "false") == "true";
+    Q_D(const Greeter);
+    return lightdm_greeter_get_select_guest_hint(d->ldmGreeter);
 }
 
 QString Greeter::autologinUserHint() const
 {
-    return getHint ("autologin-user");
+    Q_D(const Greeter);
+    return QString::fromUtf8(lightdm_greeter_get_autologin_user_hint(d->ldmGreeter));
 }
 
 bool Greeter::autologinGuestHint() const
 {
-    return d->hints.value ("autologin-guest", "false") == "true";
+    Q_D(const Greeter);
+    return lightdm_greeter_get_autologin_guest_hint(d->ldmGreeter);
 }
 
 int Greeter::autologinTimeoutHint() const
 {
-    return d->hints.value ("autologin-timeout", "0").toInt ();
+    Q_D(const Greeter);
+    return lightdm_greeter_get_autologin_timeout_hint(d->ldmGreeter);
+}
+
+QString Greeter::hostname() const
+{
+    return QString::fromUtf8(lightdm_get_hostname());
 }
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+#include "greeter_moc5.cpp"
+#else
+#include "greeter_moc4.cpp"
+#endif