4 #include "sessionsmodel.h"
7 #include <security/pam_appl.h>
9 #include <QtNetwork/QHostInfo> //needed for localHostName
10 #include <QtCore/QDebug>
11 #include <QtCore/QDir>
12 #include <QtCore/QVariant>
13 #include <QtCore/QFile>
14 #include <QtCore/QSocketNotifier>
15 #include <QtDBus/QDBusPendingReply>
16 #include <QtDBus/QDBusInterface>
17 #include <QtDBus/QDBusReply>
21 /* Messages from the greeter to the server */
22 GREETER_MESSAGE_CONNECT = 1,
23 GREETER_MESSAGE_LOGIN = 2,
24 GREETER_MESSAGE_LOGIN_AS_GUEST = 3,
25 GREETER_MESSAGE_CONTINUE_AUTHENTICATION = 4,
26 GREETER_MESSAGE_START_SESSION = 5,
27 GREETER_MESSAGE_CANCEL_AUTHENTICATION = 6,
28 GREETER_MESSAGE_GET_USER_DEFAULTS = 7,
30 /* Messages from the server to the greeter */
31 GREETER_MESSAGE_CONNECTED = 101,
32 GREETER_MESSAGE_QUIT = 102,
33 GREETER_MESSAGE_PROMPT_AUTHENTICATION = 103,
34 GREETER_MESSAGE_END_AUTHENTICATION = 104,
35 GREETER_MESSAGE_USER_DEFAULTS = 106
40 using namespace QLightDM;
46 QString defaultLayout;
47 QString defaultSession;
50 bool guestAccountSupported;
52 SessionsModel *sessionsModel;
55 QDBusInterface* lightdmInterface;
56 QDBusInterface* powerManagementInterface;
57 QDBusInterface* consoleKitInterface;
64 bool inAuthentication;
66 QString authenticationUser;
70 Greeter::Greeter(QObject *parent) :
74 d->readBuffer = (char *)malloc (HEADER_SIZE);
77 d->sessionsModel = new SessionsModel(this);
86 static int intLength()
91 static int stringLength(QString value)
93 QByteArray a = value.toUtf8();
94 return intLength() + a.size();
97 void Greeter::writeInt(int value)
100 buffer[0] = value >> 24;
101 buffer[1] = (value >> 16) & 0xFF;
102 buffer[2] = (value >> 8) & 0xFF;
103 buffer[3] = value & 0xFF;
104 if (write(d->toServerFd, buffer, intLength()) != intLength()) {
105 qDebug() << "Error writing to server";
109 void Greeter::writeString(QString value)
111 QByteArray a = value.toUtf8();
113 if (write(d->toServerFd, a.data(), a.size()) != a.size()) {
114 qDebug() << "Error writing to server";
118 void Greeter::writeHeader(int id, int length)
124 void Greeter::flush()
126 fsync(d->toServerFd);
129 int Greeter::getPacketLength()
131 int offset = intLength();
132 return readInt(&offset);
135 int Greeter::readInt(int *offset)
137 if(d->nRead - *offset < intLength()) {
138 qDebug() << "Not enough space for int, need " << intLength() << ", got " << (d->nRead - *offset);
142 char *buffer = d->readBuffer + *offset;
143 int value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
144 *offset += intLength();
148 QString Greeter::readString(int *offset)
150 int length = readInt(offset);
151 if(d->nRead - *offset < length) {
152 qDebug() << "Not enough space for string, need " << length << ", got " << (d->nRead - *offset);
155 char *start = d->readBuffer + *offset;
157 return QString::fromUtf8(start, length);
160 void Greeter::connectToServer()
162 QDBusConnection busType = QDBusConnection::systemBus();
163 QString ldmBus(qgetenv("LDM_BUS"));
164 if(ldmBus == QLatin1String("SESSION")) {
165 busType = QDBusConnection::sessionBus();
168 d->lightdmInterface = new QDBusInterface("org.lightdm.LightDisplayManager", "/org/lightdm/LightDisplayManager", "org.lightdm.LightDisplayManager", busType);
169 d->powerManagementInterface = new QDBusInterface("org.freedesktop.PowerManagement","/org/freedesktop/PowerManagement", "org.freedesktop.PowerManagement");
170 d->consoleKitInterface = new QDBusInterface("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit");
173 file = d->lightdmInterface->property("ConfigFile").toString();
174 qDebug() << "Loading configuration from " << file;
175 d->config = new Config(file, this);
177 char* fd = getenv("LDM_TO_SERVER_FD");
179 qDebug() << "No LDM_TO_SERVER_FD environment variable";
182 d->toServerFd = atoi(fd);
185 qDebug() << "***connecting to server";
187 qDebug() << toServer.open(d->toServerFd, QIODevice::WriteOnly);
189 fd = getenv("LDM_FROM_SERVER_FD");
191 qDebug() << "No LDM_FROM_SERVER_FD environment variable";
194 d->fromServerFd = atoi(fd);
196 d->n = new QSocketNotifier(d->fromServerFd, QSocketNotifier::Read);
197 connect(d->n, SIGNAL(activated(int)), this, SLOT(onRead(int)));
199 qDebug() << "Connecting to display manager...";
200 writeHeader(GREETER_MESSAGE_CONNECT, 0);
204 void Greeter::login(const QString &username)
206 d->inAuthentication = true;
207 d->isAuthenticated = false;
208 d->authenticationUser = username;
209 qDebug() << "Starting authentication for user " << username << "...";
210 writeHeader(GREETER_MESSAGE_LOGIN, stringLength(username));
211 writeString(username);
215 void Greeter::loginAsGuest()
217 d->inAuthentication = true;
218 d->isAuthenticated = false;
219 d->authenticationUser = "";
220 qDebug() << "Starting authentication for guest account";
221 writeHeader(GREETER_MESSAGE_LOGIN_AS_GUEST, 0);
225 void Greeter::provideSecret(const QString &secret)
227 qDebug() << "Providing secret to display manager";
228 writeHeader(GREETER_MESSAGE_CONTINUE_AUTHENTICATION, intLength() + stringLength(secret));
229 // FIXME: Could be multiple secrets required
235 void Greeter::cancelAuthentication()
237 qDebug() << "Cancelling authentication";
238 writeHeader(GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0);
242 bool Greeter::inAuthentication() const
244 return d->inAuthentication;
247 bool Greeter::isAuthenticated() const
249 return d->isAuthenticated;
252 QString Greeter::authenticationUser() const
254 return d->authenticationUser;
257 void Greeter::startSession(const QString &session, const QString &language)
259 qDebug() << "Starting session " << session << " with language " << language;
260 writeHeader(GREETER_MESSAGE_START_SESSION, stringLength(session) + stringLength(language));
261 writeString(session);
262 writeString(language);
266 void Greeter::startSessionWithDefaults()
268 startSession(NULL, NULL);
271 void Greeter::onRead(int fd)
273 //qDebug() << "Reading from server";
275 int nToRead = HEADER_SIZE;
276 if(d->nRead >= HEADER_SIZE)
277 nToRead += getPacketLength();
280 nRead = read(fd, d->readBuffer + d->nRead, nToRead - d->nRead);
283 qDebug() << "Error reading from server";
288 qDebug() << "EOF reading from server";
292 //qDebug() << "Read " << nRead << "octets";
294 if(d->nRead != nToRead)
297 /* If have header, rerun for content */
298 if(d->nRead == HEADER_SIZE)
300 nToRead = getPacketLength();
303 d->readBuffer = (char *)realloc(d->readBuffer, HEADER_SIZE + nToRead);
310 int id = readInt(&offset);
312 int nMessages, returnCode;
315 case GREETER_MESSAGE_CONNECTED:
316 d->theme = readString(&offset);
317 d->defaultLayout = readString(&offset);
318 d->defaultSession = readString(&offset);
319 d->timedUser = readString(&offset);
320 d->loginDelay = readInt(&offset);
321 d->guestAccountSupported = readInt(&offset) != 0;
322 qDebug() << "Connected theme=" << d->theme << " default-layout=" << d->defaultLayout << " default-session=" << d->defaultSession << " timed-user=" << d->timedUser << " login-delay" << d->loginDelay << " guestAccountSupported" << d->guestAccountSupported;
324 /* Set timeout for default login */
325 if(d->timedUser != "" && d->loginDelay > 0)
327 qDebug() << "Logging in as " << d->timedUser << " in " << d->loginDelay << " seconds";
328 //FIXME: d->login_timeout = g_timeout_add (d->login_delay * 1000, timed_login_cb, greeter);
332 case GREETER_MESSAGE_QUIT:
333 qDebug() << "Got quit request from server";
336 case GREETER_MESSAGE_PROMPT_AUTHENTICATION:
337 nMessages = readInt(&offset);
338 qDebug() << "Prompt user with " << nMessages << " message(s)";
339 for(int i = 0; i < nMessages; i++)
341 int msg_style = readInt (&offset);
342 QString msg = readString (&offset);
344 // FIXME: Should stop on prompts?
347 case PAM_PROMPT_ECHO_OFF:
348 case PAM_PROMPT_ECHO_ON:
349 emit showPrompt(msg);
355 emit showMessage(msg);
360 case GREETER_MESSAGE_END_AUTHENTICATION:
361 returnCode = readInt(&offset);
362 qDebug() << "Authentication complete with return code " << returnCode;
363 d->isAuthenticated = (returnCode == 0);
364 if(!d->isAuthenticated) {
365 d->authenticationUser = "";
367 emit authenticationComplete(d->isAuthenticated);
368 d->inAuthentication = false;
371 qDebug() << "Unknown message from server: " << id;
377 QString Greeter::hostname() const
379 return QHostInfo::localHostName();
382 QString Greeter::theme() const
387 QVariant Greeter::getProperty(const QString &name) const
389 return QVariant(); //FIXME TODO
392 QString Greeter::defaultLanguage() const
394 return getenv("LANG");
397 QString Greeter::defaultLayout() const
399 return d->defaultLayout;
402 QString Greeter::defaultSession() const
404 return d->defaultSession;
407 bool Greeter::guestAccountSupported() const
409 return d->guestAccountSupported;
412 QString Greeter::timedLoginUser() const
417 int Greeter::timedLoginDelay() const
419 return d->loginDelay;
422 Config* Greeter::config() const
427 bool Greeter::canSuspend() const
429 QDBusReply<bool> reply = d->powerManagementInterface->call("CanSuspend");
431 return reply.value();
436 void Greeter::suspend()
438 d->powerManagementInterface->call("Suspend");
441 bool Greeter::canHibernate() const
443 QDBusReply<bool> reply = d->powerManagementInterface->call("CanHibernate");
445 return reply.value();
450 void Greeter::hibernate()
452 d->powerManagementInterface->call("Hibernate");
455 bool Greeter::canShutdown() const
457 QDBusReply<bool> reply = d->consoleKitInterface->call("CanStop");
459 return reply.value();
464 void Greeter::shutdown()
466 d->consoleKitInterface->call("stop");
469 bool Greeter::canRestart() const
471 QDBusReply<bool> reply = d->consoleKitInterface->call("CanRestart");
473 return reply.value();
478 void Greeter::restart()
480 d->consoleKitInterface->call("Restart");