]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - liblightdm-gobject/greeter.c
Add g_return_if_fail macros to all the liblightdm-gobject methods
[sojka/lightdm.git] / liblightdm-gobject / greeter.c
1 /*
2  * Copyright (C) 2010 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  *
5  * This library is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License as published by the Free
7  * Software Foundation; either version 3 of the License, or (at your option) any
8  * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
9  * license.
10  */
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <locale.h>
15 #include <sys/utsname.h>
16
17 #include <gio/gdesktopappinfo.h>
18 #include <security/pam_appl.h>
19 #include <libxklavier/xklavier.h>
20
21 #include "greeter.h"
22 #include "greeter-protocol.h"
23
24 enum {
25     PROP_0,
26     PROP_HOSTNAME,
27     PROP_NUM_USERS,
28     PROP_USERS,
29     PROP_DEFAULT_LANGUAGE,
30     PROP_LAYOUTS,
31     PROP_LAYOUT,
32     PROP_SESSIONS,
33     PROP_DEFAULT_SESSION,
34     PROP_TIMED_LOGIN_USER,
35     PROP_TIMED_LOGIN_DELAY,
36     PROP_AUTHENTICATION_USER,
37     PROP_IN_AUTHENTICATION,
38     PROP_IS_AUTHENTICATED,
39     PROP_CAN_SUSPEND,
40     PROP_CAN_HIBERNATE,
41     PROP_CAN_RESTART,
42     PROP_CAN_SHUTDOWN
43 };
44
45 enum {
46     CONNECTED,
47     SHOW_PROMPT,
48     SHOW_MESSAGE,
49     SHOW_ERROR,
50     AUTHENTICATION_COMPLETE,
51     TIMED_LOGIN,
52     QUIT,
53     LAST_SIGNAL
54 };
55 static guint signals[LAST_SIGNAL] = { 0 };
56
57 struct _LdmGreeterPrivate
58 {
59     GDBusConnection *lightdm_bus;
60
61     GDBusConnection *system_bus;
62
63     GDBusProxy *session_proxy, *user_proxy;
64
65     GIOChannel *to_server_channel, *from_server_channel;
66     gchar *read_buffer;
67     gsize n_read;
68
69     Display *display;
70
71     gchar *hostname;
72
73     gchar *theme;
74     GKeyFile *theme_file;
75
76     gboolean have_users;
77     GList *users;
78
79     gboolean have_languages;
80     GList *languages;
81
82     gchar *default_layout;
83     XklEngine *xkl_engine;
84     XklConfigRec *xkl_config;
85     gboolean have_layouts;
86     GList *layouts;
87     gchar *layout;
88
89     gboolean have_sessions;
90     GList *sessions;
91     gchar *default_session;
92
93     gchar *authentication_user;
94     gboolean in_authentication;
95     gboolean is_authenticated;
96
97     gchar *timed_user;
98     gint login_delay;
99     guint login_timeout;
100 };
101
102 G_DEFINE_TYPE (LdmGreeter, ldm_greeter, G_TYPE_OBJECT);
103
104 #define HEADER_SIZE 8
105
106 /**
107  * ldm_greeter_new:
108  *
109  * Create a new greeter.
110  *
111  * Return value: the new #LdmGreeter
112  **/
113 LdmGreeter *
114 ldm_greeter_new ()
115 {
116     return g_object_new (LDM_TYPE_GREETER, NULL);
117 }
118
119 static gboolean
120 timed_login_cb (gpointer data)
121 {
122     LdmGreeter *greeter = data;
123
124     greeter->priv->login_timeout = 0;
125     g_signal_emit (G_OBJECT (greeter), signals[TIMED_LOGIN], 0, greeter->priv->timed_user);
126
127     return FALSE;
128 }
129
130 static guint32
131 int_length ()
132 {
133     return 4;
134 }
135
136 static void
137 write_int (LdmGreeter *greeter, guint32 value)
138 {
139     gchar buffer[4];
140     buffer[0] = value >> 24;
141     buffer[1] = (value >> 16) & 0xFF;
142     buffer[2] = (value >> 8) & 0xFF;
143     buffer[3] = value & 0xFF;
144     if (g_io_channel_write_chars (greeter->priv->to_server_channel, buffer, int_length (), NULL, NULL) != G_IO_STATUS_NORMAL)
145         g_warning ("Error writing to server");
146 }
147
148 static void
149 write_string (LdmGreeter *greeter, const gchar *value)
150 {
151     write_int (greeter, strlen (value));
152     g_io_channel_write_chars (greeter->priv->to_server_channel, value, -1, NULL, NULL);
153 }
154
155 static guint32
156 read_int (LdmGreeter *greeter, gsize *offset)
157 {
158     guint32 value;
159     gchar *buffer;
160     if (greeter->priv->n_read - *offset < int_length ())
161     {
162         g_warning ("Not enough space for int, need %i, got %zi", int_length (), greeter->priv->n_read - *offset);
163         return 0;
164     }
165     buffer = greeter->priv->read_buffer + *offset;
166     value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
167     *offset += int_length ();
168     return value;
169 }
170
171 static gchar *
172 read_string (LdmGreeter *greeter, gsize *offset)
173 {
174     guint32 length;
175     gchar *value;
176
177     length = read_int (greeter, offset);
178     if (greeter->priv->n_read - *offset < length)
179     {
180         g_warning ("Not enough space for string, need %u, got %zu", length, greeter->priv->n_read - *offset);
181         return g_strdup ("");
182     }
183
184     value = g_malloc (sizeof (gchar) * (length + 1));
185     memcpy (value, greeter->priv->read_buffer + *offset, length);
186     value[length] = '\0';
187     *offset += length;
188
189     return value;
190 }
191
192 static guint32
193 string_length (const gchar *value)
194 {
195     return int_length () + strlen (value);
196 }
197
198 static void
199 write_header (LdmGreeter *greeter, guint32 id, guint32 length)
200 {
201     write_int (greeter, id);
202     write_int (greeter, length);
203 }
204
205 static guint32 get_packet_length (LdmGreeter *greeter)
206 {
207     gsize offset = 4;
208     return read_int (greeter, &offset);
209 }
210
211 static void
212 flush (LdmGreeter *greeter)
213 {
214     g_io_channel_flush (greeter->priv->to_server_channel, NULL);
215 }
216
217 static void
218 handle_prompt_authentication (LdmGreeter *greeter, gsize *offset)
219 {
220     int n_messages, i;
221
222     n_messages = read_int (greeter, offset);
223     g_debug ("Prompt user with %d message(s)", n_messages);
224
225     for (i = 0; i < n_messages; i++)
226     {
227         int msg_style;
228         gchar *msg;
229
230         msg_style = read_int (greeter, offset);
231         msg = read_string (greeter, offset);
232
233         // FIXME: Should stop on prompts?
234         switch (msg_style)
235         {
236         case PAM_PROMPT_ECHO_OFF:
237         case PAM_PROMPT_ECHO_ON:
238             g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, msg);
239             break;
240         case PAM_ERROR_MSG:
241             g_signal_emit (G_OBJECT (greeter), signals[SHOW_ERROR], 0, msg);
242             break;
243         case PAM_TEXT_INFO:
244             g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, msg);
245             break;
246         }
247
248         g_free (msg);
249     }
250 }
251
252 static gboolean
253 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
254 {
255     LdmGreeter *greeter = data;
256     gsize n_to_read, n_read, offset;
257     GIOStatus status;
258     guint32 id, return_code;
259     GError *error = NULL;
260
261     n_to_read = HEADER_SIZE;
262     if (greeter->priv->n_read >= HEADER_SIZE)
263         n_to_read += get_packet_length (greeter);
264
265     status = g_io_channel_read_chars (greeter->priv->from_server_channel,
266                                       greeter->priv->read_buffer + greeter->priv->n_read,
267                                       n_to_read - greeter->priv->n_read,
268                                       &n_read,
269                                       &error);
270     if (status != G_IO_STATUS_NORMAL)
271         g_warning ("Error reading from server: %s", error->message);
272     g_clear_error (&error);
273     if (status != G_IO_STATUS_NORMAL)
274         return TRUE;
275
276     greeter->priv->n_read += n_read;
277     if (greeter->priv->n_read != n_to_read)
278         return TRUE;
279
280     /* If have header, rerun for content */
281     if (greeter->priv->n_read == HEADER_SIZE)
282     {
283         n_to_read = get_packet_length (greeter);
284         if (n_to_read > 0)
285         {
286             greeter->priv->read_buffer = g_realloc (greeter->priv->read_buffer, HEADER_SIZE + n_to_read);
287             return from_server_cb (source, condition, data);
288         }
289     }
290
291     offset = 0;
292     id = read_int (greeter, &offset);
293     read_int (greeter, &offset);
294     switch (id)
295     {
296     case GREETER_MESSAGE_CONNECTED:
297         greeter->priv->theme = read_string (greeter, &offset);
298         greeter->priv->default_layout = read_string (greeter, &offset);
299         greeter->priv->default_session = read_string (greeter, &offset);
300         greeter->priv->timed_user = read_string (greeter, &offset);
301         greeter->priv->login_delay = read_int (greeter, &offset);
302
303         g_debug ("Connected theme=%s default-layout=%s default-session=%s timed-user=%s login-delay=%d",
304                  greeter->priv->theme,
305                  greeter->priv->default_layout, greeter->priv->default_session,
306                  greeter->priv->timed_user, greeter->priv->login_delay);
307
308         /* Set timeout for default login */
309         if (greeter->priv->timed_user[0] != '\0' && greeter->priv->login_delay > 0)
310         {
311             g_debug ("Logging in as %s in %d seconds", greeter->priv->timed_user, greeter->priv->login_delay);
312             greeter->priv->login_timeout = g_timeout_add (greeter->priv->login_delay * 1000, timed_login_cb, greeter);
313         }
314         g_signal_emit (G_OBJECT (greeter), signals[CONNECTED], 0);
315         break;
316     case GREETER_MESSAGE_QUIT:
317         g_debug ("Got quit request from server");
318         g_signal_emit (G_OBJECT (greeter), signals[QUIT], 0);
319         break;
320     case GREETER_MESSAGE_PROMPT_AUTHENTICATION:
321         handle_prompt_authentication (greeter, &offset);
322         break;
323     case GREETER_MESSAGE_END_AUTHENTICATION:
324         return_code = read_int (greeter, &offset);
325         g_debug ("Authentication complete with return code %d", return_code);
326         greeter->priv->is_authenticated = (return_code == 0);
327         if (!greeter->priv->is_authenticated)
328         {
329             g_free (greeter->priv->authentication_user);
330             greeter->priv->authentication_user = NULL;
331         }
332         g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
333         break;
334     default:
335         g_warning ("Unknown message from server: %d", id);
336         break;
337     }
338
339     greeter->priv->n_read = 0;
340
341     return TRUE;
342 }
343
344 /**
345  * ldm_greeter_connect_to_server:
346  * @greeter: The greeter to connect
347  *
348  * Connects the greeter to the display manager.
349  *
350  * Return value: TRUE if successfully connected
351  **/
352 gboolean
353 ldm_greeter_connect_to_server (LdmGreeter *greeter)
354 {
355     GError *error = NULL;
356     const gchar *bus_address, *fd;
357     GBusType bus_type = G_BUS_TYPE_SYSTEM;
358
359     g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
360
361     greeter->priv->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
362     if (!greeter->priv->system_bus)
363         g_warning ("Failed to connect to system bus: %s", error->message);
364     g_clear_error (&error);
365     if (!greeter->priv->system_bus)
366         return FALSE;
367
368     bus_address = getenv ("LDM_BUS");
369     if (bus_address && strcmp (bus_address, "SESSION") == 0)
370         bus_type = G_BUS_TYPE_SESSION;
371
372     greeter->priv->lightdm_bus = g_bus_get_sync (bus_type, NULL, &error);
373     if (!greeter->priv->lightdm_bus)
374         g_warning ("Failed to connect to LightDM bus: %s", error->message);
375     g_clear_error (&error);
376     if (!greeter->priv->lightdm_bus)
377         return FALSE;
378
379     fd = getenv ("LDM_TO_SERVER_FD");
380     if (!fd)
381     {
382         g_warning ("No LDM_TO_SERVER_FD environment variable");
383         return FALSE;
384     }
385     greeter->priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
386     g_io_channel_set_encoding (greeter->priv->to_server_channel, NULL, NULL);
387
388     fd = getenv ("LDM_FROM_SERVER_FD");
389     if (!fd)
390     {
391         g_warning ("No LDM_FROM_SERVER_FD environment variable");
392         return FALSE;
393     }
394     greeter->priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
395     g_io_channel_set_encoding (greeter->priv->from_server_channel, NULL, NULL);
396     g_io_add_watch (greeter->priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
397
398     greeter->priv->session_proxy = g_dbus_proxy_new_sync (greeter->priv->lightdm_bus,
399                                                           G_DBUS_PROXY_FLAGS_NONE,
400                                                           NULL,
401                                                           "org.lightdm.LightDisplayManager",
402                                                           "/org/lightdm/LightDisplayManager/Session",
403                                                           "org.lightdm.LightDisplayManager.Session",
404                                                           NULL, NULL);
405     greeter->priv->user_proxy = g_dbus_proxy_new_sync (greeter->priv->lightdm_bus,
406                                                        G_DBUS_PROXY_FLAGS_NONE,
407                                                        NULL,
408                                                        "org.lightdm.LightDisplayManager",
409                                                        "/org/lightdm/LightDisplayManager/Users",
410                                                        "org.lightdm.LightDisplayManager.Users",
411                                                        NULL, NULL);
412
413     g_debug ("Connecting to display manager...");
414     write_header (greeter, GREETER_MESSAGE_CONNECT, 0);
415     flush (greeter);
416
417     return TRUE;
418 }
419
420 /**
421  * ldm_greeter_get_hostname:
422  * @greeter: a #LdmGreeter
423  *
424  * Return value: The host this greeter is displaying
425  **/
426 const gchar *
427 ldm_greeter_get_hostname (LdmGreeter *greeter)
428 {
429     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
430
431     if (!greeter->priv->hostname)
432     {
433         struct utsname info;
434         uname (&info);
435         greeter->priv->hostname = g_strdup (info.nodename);
436     }
437
438     return greeter->priv->hostname;
439 }
440
441 /**
442  * ldm_greeter_get_theme:
443  * @greeter: a #LdmGreeter
444  *
445  * Return value: The theme this greeter is using
446  **/
447 const gchar *
448 ldm_greeter_get_theme (LdmGreeter *greeter)
449 {
450     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
451     return greeter->priv->theme;
452 }
453
454 static void
455 load_theme (LdmGreeter *greeter)
456 {
457     GError *error = NULL;
458
459     if (greeter->priv->theme_file)
460         return;
461
462     greeter->priv->theme_file = g_key_file_new ();
463     if (!g_key_file_load_from_file (greeter->priv->theme_file, greeter->priv->theme, G_KEY_FILE_NONE, &error))
464         g_warning ("Failed to read theme file: %s", error->message);
465     g_clear_error (&error);
466 }
467
468 /**
469  * ldm_greeter_get_string_property:
470  * @greeter: a #LdmGreeter
471  * @name: the name of the property to get
472  *
473  * Return value: The value of this property or NULL if it is not defined
474  **/
475 gchar *
476 ldm_greeter_get_string_property (LdmGreeter *greeter, const gchar *name)
477 {
478     GError *error = NULL;
479     gchar *result;
480
481     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
482     g_return_val_if_fail (name != NULL, NULL);
483
484     load_theme (greeter);
485
486     result = g_key_file_get_string (greeter->priv->theme_file, "theme", name, &error);
487     if (!result)
488         g_warning ("Error reading theme property: %s", error->message); // FIXME: Can handle G_KEY_FILE_ERROR_KEY_NOT_FOUND and G_KEY_FILE_ERROR_GROUP_NOT_FOUND
489     g_clear_error (&error);
490
491     return result;
492 }
493
494 /**
495  * ldm_greeter_get_integer_property:
496  * @greeter: a #LdmGreeter
497  * @name: the name of the property to get
498  *
499  * Return value: The value of this property or 0 if it is not defined
500  **/
501 gint
502 ldm_greeter_get_integer_property (LdmGreeter *greeter, const gchar *name)
503 {
504     GError *error = NULL;
505     gint result;
506
507     g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
508     g_return_val_if_fail (name != NULL, 0);
509
510     load_theme (greeter);
511
512     result = g_key_file_get_integer (greeter->priv->theme_file, "theme", name, &error);
513     if (!result)
514         g_warning ("Error reading theme property: %s", error->message); // FIXME: Can handle G_KEY_FILE_ERROR_KEY_NOT_FOUND and G_KEY_FILE_ERROR_GROUP_NOT_FOUND
515     g_clear_error (&error);
516
517     return result;
518 }
519
520 /**
521  * ldm_greeter_get_boolean_property:
522  * @greeter: a #LdmGreeter
523  * @name: the name of the property to get
524  *
525  * Return value: The value of this property or FALSE if it is not defined
526  **/
527 gboolean
528 ldm_greeter_get_boolean_property (LdmGreeter *greeter, const gchar *name)
529 {
530     GError *error = NULL;
531     gboolean result;
532
533     g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
534     g_return_val_if_fail (name != NULL, FALSE);
535
536     load_theme (greeter);
537
538     result = g_key_file_get_boolean (greeter->priv->theme_file, "theme", name, &error);
539     if (!result)
540         g_warning ("Error reading theme property: %s", error->message); // FIXME: Can handle G_KEY_FILE_ERROR_KEY_NOT_FOUND and G_KEY_FILE_ERROR_GROUP_NOT_FOUND
541     g_clear_error (&error);
542
543     return result;
544 }
545
546 static void
547 update_users (LdmGreeter *greeter)
548 {
549     GVariant *result, *user_array;
550     GVariantIter iter;
551     gchar *name, *real_name, *image;
552     gboolean logged_in;
553     GError *error = NULL;
554
555     if (greeter->priv->have_users)
556         return;
557
558     g_debug ("Getting user list...");
559     result = g_dbus_proxy_call_sync (greeter->priv->user_proxy,
560                                      "GetUsers",
561                                      NULL,
562                                      G_DBUS_CALL_FLAGS_NONE,
563                                      -1,
564                                      NULL,
565                                      &error);
566     if (!result)
567         g_warning ("Failed to get users: %s", error->message);
568     g_clear_error (&error);
569     if (!result)
570         return;
571
572     if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(a(sssb))")))
573     {
574         g_warning ("Unknown type returned");
575         g_variant_unref (result);
576         return;
577     }
578     user_array = g_variant_get_child_value (result, 0);
579     g_debug ("Got %zi users", g_variant_n_children (user_array));
580     g_variant_iter_init (&iter, user_array);
581     while (g_variant_iter_next (&iter, "(&s&s&sb)", &name, &real_name, &image, &logged_in))
582     {
583         LdmUser *user;
584
585         user = ldm_user_new (greeter, name, real_name, image, logged_in);
586         greeter->priv->users = g_list_append (greeter->priv->users, user);
587     }
588     greeter->priv->have_users = TRUE;
589
590     g_variant_unref (result);
591 }
592
593 /**
594  * ldm_greeter_get_num_users:
595  * @greeter: a #LdmGreeter
596  *
597  * Return value: The number of users able to log in
598  **/
599 gint
600 ldm_greeter_get_num_users (LdmGreeter *greeter)
601 {
602     g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
603     update_users (greeter);
604     return g_list_length (greeter->priv->users);
605 }
606
607 /**
608  * ldm_greeter_get_users:
609  * @greeter: A #LdmGreeter
610  *
611  * Get a list of users to present to the user.  This list may be a subset of the
612  * available users and may be empty depending on the server configuration.
613  *
614  * Return value: (element-type LdmUser): A list of #LdmUser that should be presented to the user.
615  **/
616 const GList *
617 ldm_greeter_get_users (LdmGreeter *greeter)
618 {
619     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
620     update_users (greeter);
621     return greeter->priv->users;
622 }
623
624 static void
625 update_languages (LdmGreeter *greeter)
626 {
627     gchar *stdout_text = NULL, *stderr_text = NULL;
628     gint exit_status;
629     gboolean result;
630     GError *error = NULL;
631
632     if (greeter->priv->have_languages)
633         return;
634
635     result = g_spawn_command_line_sync ("locale -a", &stdout_text, &stderr_text, &exit_status, &error);
636     if (!result || exit_status != 0)
637         g_warning ("Failed to get languages, locale -a returned %d: %s", exit_status, error->message);
638     else
639     {
640         gchar **tokens;
641         int i;
642
643         tokens = g_strsplit_set (stdout_text, "\n\r", -1);
644         for (i = 0; tokens[i]; i++)
645         {
646             LdmLanguage *language;
647             gchar *code;
648
649             code = g_strchug (tokens[i]);
650             if (code[0] == '\0')
651                 continue;
652
653             /* Ignore the non-interesting languages */
654             if (strcmp (code, "C") == 0 || strcmp (code, "POSIX") == 0)
655                 continue;
656
657             language = ldm_language_new (code);
658             greeter->priv->languages = g_list_append (greeter->priv->languages, language);
659         }
660
661         g_strfreev (tokens);
662     }
663
664     g_clear_error (&error);
665     g_free (stdout_text);
666     g_free (stderr_text);
667
668     greeter->priv->have_languages = TRUE;
669 }
670
671 /**
672  * ldm_greeter_get_default_language:
673  * @greeter: A #LdmGreeter
674  *
675  * Get the default language.
676  *
677  * Return value: The default language.
678  **/
679 const gchar *
680 ldm_greeter_get_default_language (LdmGreeter *greeter)
681 {
682     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
683     return getenv ("LANG");
684 }
685
686 /**
687  * ldm_greeter_get_languages:
688  * @greeter: A #LdmGreeter
689  *
690  * Get a list of languages to present to the user.
691  *
692  * Return value: (element-type LdmLanguage): A list of #LdmLanguage that should be presented to the user.
693  **/
694 const GList *
695 ldm_greeter_get_languages (LdmGreeter *greeter)
696 {
697     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
698     update_languages (greeter);
699     return greeter->priv->languages;
700 }
701
702 const gchar *
703 ldm_greeter_get_default_layout (LdmGreeter *greeter)
704 {
705     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
706     return greeter->priv->default_layout;
707 }
708
709 static void
710 layout_cb (XklConfigRegistry *config,
711            const XklConfigItem *item,
712            gpointer data)
713 {
714     LdmGreeter *greeter = data;
715     LdmLayout *layout;
716
717     layout = ldm_layout_new (item->name, item->short_description, item->description);
718     greeter->priv->layouts = g_list_append (greeter->priv->layouts, layout);
719 }
720
721 static void
722 setup_display (LdmGreeter *greeter)
723 {
724     if (!greeter->priv->display)
725         greeter->priv->display = XOpenDisplay (NULL);
726 }
727
728 static void
729 setup_xkl (LdmGreeter *greeter)
730 {
731     setup_display (greeter);
732     greeter->priv->xkl_engine = xkl_engine_get_instance (greeter->priv->display);
733     greeter->priv->xkl_config = xkl_config_rec_new ();
734     if (!xkl_config_rec_get_from_server (greeter->priv->xkl_config, greeter->priv->xkl_engine))
735         g_warning ("Failed to get Xkl configuration from server");
736     greeter->priv->layout = g_strdup (greeter->priv->xkl_config->layouts[0]);
737 }
738
739 /**
740  * ldm_greeter_get_layouts:
741  * @greeter: A #LdmGreeter
742  *
743  * Get a list of keyboard layouts to present to the user.
744  *
745  * Return value: (element-type LdmLayout): A list of #LdmLayout that should be presented to the user.
746  **/
747 const GList *
748 ldm_greeter_get_layouts (LdmGreeter *greeter)
749 {
750     XklConfigRegistry *registry;
751
752     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
753
754     if (greeter->priv->have_layouts)
755         return greeter->priv->layouts;
756
757     setup_xkl (greeter);
758
759     registry = xkl_config_registry_get_instance (greeter->priv->xkl_engine);
760     xkl_config_registry_load (registry, FALSE);
761     xkl_config_registry_foreach_layout (registry, layout_cb, greeter);
762     g_object_unref (registry);
763     greeter->priv->have_layouts = TRUE;
764
765     return greeter->priv->layouts;
766 }
767
768 /**
769  * ldm_greeter_set_layout:
770  * @greeter: A #LdmGreeter
771  * @layout: The layout to use
772  *
773  * Set the layout for this session.
774  **/
775 void
776 ldm_greeter_set_layout (LdmGreeter *greeter, const gchar *layout)
777 {
778     XklConfigRec *config;
779
780     g_return_if_fail (LDM_IS_GREETER (greeter));
781     g_return_if_fail (layout != NULL);
782
783     g_debug ("Setting keyboard layout to %s", layout);
784
785     setup_xkl (greeter);
786
787     config = xkl_config_rec_new ();
788     config->layouts = g_malloc (sizeof (gchar *) * 2);
789     config->model = g_strdup (greeter->priv->xkl_config->model);
790     config->layouts[0] = g_strdup (layout);
791     config->layouts[1] = NULL;
792     if (!xkl_config_rec_activate (config, greeter->priv->xkl_engine))
793         g_warning ("Failed to activate XKL config");
794     else
795         greeter->priv->layout = g_strdup (layout);
796     g_object_unref (config);
797 }
798
799 /**
800  * ldm_greeter_get_layout:
801  * @greeter: A #LdmGreeter
802  *
803  * Get the current keyboard layout.
804  *
805  * Return value: The currently active layout for this user.
806  **/
807 const gchar *
808 ldm_greeter_get_layout (LdmGreeter *greeter)
809 {
810     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
811     setup_xkl (greeter);
812     return greeter->priv->layout;
813 }
814
815 static void
816 update_sessions (LdmGreeter *greeter)
817 {
818     GDir *directory;
819     GError *error = NULL;
820
821     if (greeter->priv->have_sessions)
822         return;
823
824     directory = g_dir_open (XSESSIONS_DIR, 0, &error);
825     if (!directory)
826         g_warning ("Failed to open sessions directory: %s", error->message);
827     g_clear_error (&error);
828     if (!directory)
829         return;
830
831     while (TRUE)
832     {
833         const gchar *filename;
834         GKeyFile *key_file;
835         gchar *key, *path;
836         gboolean result;
837
838         filename = g_dir_read_name (directory);
839         if (filename == NULL)
840             break;
841
842         if (!g_str_has_suffix (filename, ".desktop"))
843             continue;
844
845         key = g_strndup (filename, strlen (filename) - strlen (".desktop"));
846         path = g_build_filename (XSESSIONS_DIR, filename, NULL);
847         g_debug ("Loading session %s", path);
848
849         key_file = g_key_file_new ();
850         result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
851         if (!result)
852             g_warning ("Failed to load session file %s: %s:", path, error->message);
853         g_clear_error (&error);
854
855         if (result && !g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL))
856         {
857             gchar *domain, *name, *comment;
858
859 #ifdef G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN
860             domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN, NULL);
861 #else
862             domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL);
863 #endif
864             name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, domain, NULL);
865             comment = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, domain, NULL);
866             if (!comment)
867                 comment = g_strdup ("");
868             if (name)
869             {
870                 g_debug ("Loaded session %s (%s, %s)", key, name, comment);
871                 greeter->priv->sessions = g_list_append (greeter->priv->sessions, ldm_session_new (key, name, comment));
872             }
873             else
874                 g_warning ("Invalid session %s: %s", path, error->message);
875             g_clear_error (&error);
876             g_free (domain);
877             g_free (name);
878             g_free (comment);
879         }
880
881         g_free (key);
882         g_free (path);
883         g_key_file_free (key_file);
884     }
885
886     g_dir_close (directory);
887
888     greeter->priv->have_sessions = TRUE;
889 }
890
891 /**
892  * ldm_greeter_get_sessions:
893  * @greeter: A #LdmGreeter
894  *
895  * Get the available sessions.
896  *
897  * Return value: (element-type LdmSession): A list of #LdmSession
898  **/
899 const GList *
900 ldm_greeter_get_sessions (LdmGreeter *greeter)
901 {
902     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
903     update_sessions (greeter);
904     return greeter->priv->sessions;
905 }
906
907 /**
908  * ldm_greeter_get_default_session:
909  * @greeter: A #LdmGreeter
910  *
911  * Get the default session to use.
912  *
913  * Return value: The session name
914  **/
915 const gchar *
916 ldm_greeter_get_default_session (LdmGreeter *greeter)
917 {
918     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
919     return greeter->priv->default_session;
920 }
921
922 /**
923  * ldm_greeter_get_timed_login_user:
924  * @greeter: A #LdmGreeter
925  *
926  * Get the user to log in by as default.
927  *
928  * Return value: A username
929  */
930 const gchar *
931 ldm_greeter_get_timed_login_user (LdmGreeter *greeter)
932 {
933     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
934     return greeter->priv->timed_user;
935 }
936
937 /**
938  * ldm_greeter_get_timed_login_delay:
939  * @greeter: A #LdmGreeter
940  *
941  * Get the number of seconds to wait until logging in as the default user.
942  *
943  * Return value: The number of seconds before logging in as the default user
944  */
945 gint
946 ldm_greeter_get_timed_login_delay (LdmGreeter *greeter)
947 {
948     g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
949     return greeter->priv->login_delay;
950 }
951
952 /**
953  * ldm_greeter_cancel_timed_login:
954  * @greeter: A #LdmGreeter
955  *
956  * Cancel the login as the default user.
957  */
958 void
959 ldm_greeter_cancel_timed_login (LdmGreeter *greeter)
960 {
961     g_return_if_fail (LDM_IS_GREETER (greeter));
962
963     if (greeter->priv->login_timeout)
964        g_source_remove (greeter->priv->login_timeout);
965     greeter->priv->login_timeout = 0;
966 }
967
968 /**
969  * ldm_greeter_start_authentication:
970  * @greeter: A #LdmGreeter
971  * @username: A username
972  *
973  * Starts the authentication procedure for a user.
974  **/
975 void
976 ldm_greeter_start_authentication (LdmGreeter *greeter, const char *username)
977 {
978     g_return_if_fail (LDM_IS_GREETER (greeter));
979     g_return_if_fail (username != NULL);
980
981     greeter->priv->is_authenticated = FALSE;
982     g_free (greeter->priv->authentication_user);
983     greeter->priv->authentication_user = g_strdup (username);
984     g_debug ("Starting authentication for user %s...", username);
985     write_header (greeter, GREETER_MESSAGE_START_AUTHENTICATION, string_length (username));
986     write_string (greeter, username);
987     flush (greeter);
988 }
989
990 /**
991  * ldm_greeter_provide_secret:
992  * @greeter: A #LdmGreeter
993  * @secret: Response to a prompt
994  *
995  * Provide secret information from a prompt.
996  **/
997 void
998 ldm_greeter_provide_secret (LdmGreeter *greeter, const gchar *secret)
999 {
1000     g_return_if_fail (LDM_IS_GREETER (greeter));
1001     g_return_if_fail (secret != NULL);
1002
1003     g_debug ("Providing secret to display manager");
1004     write_header (greeter, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, int_length () + string_length (secret));
1005     // FIXME: Could be multiple secrets required
1006     write_int (greeter, 1);
1007     write_string (greeter, secret);
1008     flush (greeter);
1009 }
1010
1011 /**
1012  * ldm_greeter_cancel_authentication:
1013  * @greeter: A #LdmGreeter
1014  *
1015  * Cancel the current user authentication.
1016  **/
1017 void
1018 ldm_greeter_cancel_authentication (LdmGreeter *greeter)
1019 {
1020     g_return_if_fail (LDM_IS_GREETER (greeter));
1021 }
1022
1023 /**
1024  * ldm_greeter_get_in_authentication:
1025  * @greeter: A #LdmGreeter
1026  *
1027  * Checks if the greeter is in the process of authenticating.
1028  *
1029  * Return value: TRUE if the greeter is authenticating a user.
1030  **/
1031 gboolean
1032 ldm_greeter_get_in_authentication (LdmGreeter *greeter)
1033 {
1034     g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1035     return greeter->priv->in_authentication;
1036 }
1037
1038 /**
1039  * ldm_greeter_get_is_authenticated:
1040  * @greeter: A #LdmGreeter
1041  *
1042  * Checks if the greeter has successfully authenticated.
1043  *
1044  * Return value: TRUE if the greeter is authenticated for login.
1045  **/
1046 gboolean
1047 ldm_greeter_get_is_authenticated (LdmGreeter *greeter)
1048 {
1049     g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1050     return greeter->priv->is_authenticated;
1051 }
1052
1053 /**
1054  * ldm_greeter_get_authentication_user:
1055  * @greeter: A #LdmGreeter
1056  *
1057  * Get the user that is being authenticated.
1058  *
1059  * Return value: The username of the authentication user being authenticated or NULL if no authentication in progress.
1060  */
1061 const gchar *
1062 ldm_greeter_get_authentication_user (LdmGreeter *greeter)
1063 {
1064     g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1065     return greeter->priv->authentication_user;
1066 }
1067
1068 /**
1069  * ldm_greeter_login:
1070  * @greeter: A #LdmGreeter
1071  * @username: The user to log in as
1072  * @session: (allow-none): The session to log into or NULL to use the default
1073  * @language: (allow-none): The language to use or NULL to use the default
1074  *
1075  * Login a user to a session.
1076  **/
1077 void
1078 ldm_greeter_login (LdmGreeter *greeter, const gchar *username, const gchar *session, const gchar *language)
1079 {
1080     g_return_if_fail (LDM_IS_GREETER (greeter));
1081     g_return_if_fail (username != NULL);
1082   
1083     if (!session)
1084         session = "";
1085     if (!language)
1086         language = "";
1087
1088     g_debug ("Logging in");
1089     write_header (greeter, GREETER_MESSAGE_LOGIN, string_length (username) + string_length (session) + string_length (language));
1090     write_string (greeter, username);
1091     write_string (greeter, session);
1092     write_string (greeter, language);
1093     flush (greeter);
1094 }
1095
1096 /**
1097  * ldm_greeter_login_with_defaults:
1098  * @greeter: A #LdmGreeter
1099  * @username: The user to log in as
1100  *
1101  * Login a user to a session using default settings for that user.
1102  **/
1103 void
1104 ldm_greeter_login_with_defaults (LdmGreeter *greeter, const gchar *username)
1105 {
1106     g_return_if_fail (LDM_IS_GREETER (greeter));
1107     g_return_if_fail (username != NULL);
1108     ldm_greeter_login (greeter, username, NULL, NULL);
1109 }
1110
1111 static gboolean
1112 upower_call_function (LdmGreeter *greeter, const gchar *function, gboolean has_result)
1113 {
1114     GDBusProxy *proxy;
1115     GVariant *result;
1116     GError *error = NULL;
1117     gboolean function_result = FALSE;
1118
1119     proxy = g_dbus_proxy_new_sync (greeter->priv->system_bus,
1120                                    G_DBUS_PROXY_FLAGS_NONE,
1121                                    NULL,
1122                                    "org.freedesktop.UPower",
1123                                    "/org/freedesktop/UPower",
1124                                    "org.freedesktop.UPower",
1125                                    NULL, NULL);
1126     result = g_dbus_proxy_call_sync (proxy,
1127                                      function,
1128                                      NULL,
1129                                      G_DBUS_CALL_FLAGS_NONE,
1130                                      -1,
1131                                      NULL,
1132                                      &error);
1133     g_object_unref (proxy);
1134
1135     if (!result)
1136         g_warning ("Error calling UPower function %s: %s", function, error->message);
1137     g_clear_error (&error);
1138     if (!result)
1139         return FALSE;
1140
1141     if (g_variant_is_of_type (result, G_VARIANT_TYPE_BOOLEAN))
1142         function_result = g_variant_get_boolean (result);
1143
1144     g_variant_unref (result);
1145     return function_result;
1146 }
1147
1148 /**
1149  * ldm_greeter_get_can_suspend:
1150  * @greeter: A #LdmGreeter
1151  *
1152  * Checks if the greeter is authorized to do a system suspend.
1153  *
1154  * Return value: TRUE if the greeter can suspend the system
1155  **/
1156 gboolean
1157 ldm_greeter_get_can_suspend (LdmGreeter *greeter)
1158 {
1159     g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1160     return upower_call_function (greeter, "SuspendAllowed", TRUE);
1161 }
1162
1163 /**
1164  * ldm_greeter_suspend:
1165  * @greeter: A #LdmGreeter
1166  *
1167  * Triggers a system suspend.
1168  **/
1169 void
1170 ldm_greeter_suspend (LdmGreeter *greeter)
1171 {
1172     g_return_if_fail (LDM_IS_GREETER (greeter));
1173     upower_call_function (greeter, "Suspend", FALSE);
1174 }
1175
1176 /**
1177  * ldm_greeter_get_can_hibernate:
1178  * @greeter: A #LdmGreeter
1179  *
1180  * Checks if the greeter is authorized to do a system hibernate.
1181  *
1182  * Return value: TRUE if the greeter can hibernate the system
1183  **/
1184 gboolean
1185 ldm_greeter_get_can_hibernate (LdmGreeter *greeter)
1186 {
1187     g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1188     return upower_call_function (greeter, "HibernateAllowed", TRUE);
1189 }
1190
1191 /**
1192  * ldm_greeter_hibernate:
1193  * @greeter: A #LdmGreeter
1194  *
1195  * Triggers a system hibernate.
1196  **/
1197 void
1198 ldm_greeter_hibernate (LdmGreeter *greeter)
1199 {
1200     g_return_if_fail (LDM_IS_GREETER (greeter));
1201     upower_call_function (greeter, "Hibernate", FALSE);
1202 }
1203
1204 static gboolean
1205 ck_call_function (LdmGreeter *greeter, const gchar *function, gboolean has_result)
1206 {
1207     GDBusProxy *proxy;
1208     GVariant *result;
1209     GError *error = NULL;
1210     gboolean function_result = FALSE;
1211
1212     proxy = g_dbus_proxy_new_sync (greeter->priv->system_bus,
1213                                    G_DBUS_PROXY_FLAGS_NONE,
1214                                    NULL,
1215                                    "org.freedesktop.ConsoleKit",
1216                                    "/org/freedesktop/ConsoleKit/Manager",
1217                                    "org.freedesktop.ConsoleKit.Manager",
1218                                    NULL, NULL);
1219     result = g_dbus_proxy_call_sync (proxy,
1220                                      function,
1221                                      NULL,
1222                                      G_DBUS_CALL_FLAGS_NONE,
1223                                      -1,
1224                                      NULL,
1225                                      &error);
1226     g_object_unref (proxy);
1227
1228     if (!result)
1229         g_warning ("Error calling ConsoleKit function %s: %s", function, error->message);
1230     g_clear_error (&error);
1231     if (!result)
1232         return FALSE;
1233
1234     if (g_variant_is_of_type (result, G_VARIANT_TYPE_BOOLEAN))
1235         function_result = g_variant_get_boolean (result);
1236
1237     g_variant_unref (result);
1238     return function_result;
1239 }
1240
1241 /**
1242  * ldm_greeter_get_can_restart:
1243  * @greeter: A #LdmGreeter
1244  *
1245  * Checks if the greeter is authorized to do a system restart.
1246  *
1247  * Return value: TRUE if the greeter can restart the system
1248  **/
1249 gboolean
1250 ldm_greeter_get_can_restart (LdmGreeter *greeter)
1251 {
1252     g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1253     return ck_call_function (greeter, "CanRestart", TRUE);
1254 }
1255
1256 /**
1257  * ldm_greeter_restart:
1258  * @greeter: A #LdmGreeter
1259  *
1260  * Triggers a system restart.
1261  **/
1262 void
1263 ldm_greeter_restart (LdmGreeter *greeter)
1264 {
1265     g_return_if_fail (LDM_IS_GREETER (greeter));
1266     ck_call_function (greeter, "Restart", FALSE);
1267 }
1268
1269 /**
1270  * ldm_greeter_get_can_shutdown:
1271  * @greeter: A #LdmGreeter
1272  *
1273  * Checks if the greeter is authorized to do a system shutdown.
1274  *
1275  * Return value: TRUE if the greeter can shutdown the system
1276  **/
1277 gboolean
1278 ldm_greeter_get_can_shutdown (LdmGreeter *greeter)
1279 {
1280     g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1281     return ck_call_function (greeter, "CanStop", TRUE);
1282 }
1283
1284 /**
1285  * ldm_greeter_shutdown:
1286  * @greeter: A #LdmGreeter
1287  *
1288  * Triggers a system shutdown.
1289  **/
1290 void
1291 ldm_greeter_shutdown (LdmGreeter *greeter)
1292 {
1293     g_return_if_fail (LDM_IS_GREETER (greeter));
1294     ck_call_function (greeter, "Stop", FALSE);
1295 }
1296
1297 /**
1298  * ldm_greeter_get_user_defaults:
1299  * @greeter: A #LdmGreeter
1300  * @username: The user to check
1301  * @language: (out): Default language for this user.
1302  * @layout: (out): Default keyboard layout for this user.
1303  * @session: (out): Default session for this user.
1304  * 
1305  * Get the default settings for a given user.
1306  **/
1307 gboolean
1308 ldm_greeter_get_user_defaults (LdmGreeter *greeter, const gchar *username, gchar **language, gchar **layout, gchar **session)
1309 {
1310     GError *error = NULL;
1311     GVariant *result;
1312     gboolean got_defaults = FALSE;
1313
1314     g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1315     g_return_val_if_fail (username != NULL, FALSE);
1316
1317     result = g_dbus_proxy_call_sync (greeter->priv->user_proxy,
1318                                      "GetUserDefaults",
1319                                      g_variant_new ("(s)", username),
1320                                      G_DBUS_CALL_FLAGS_NONE,
1321                                      -1,
1322                                      NULL,
1323                                      &error);
1324
1325     if (!result)
1326         g_warning ("Failed to get user defaults: %s", error->message);
1327     g_clear_error (&error);
1328
1329     if (!result)
1330         return FALSE;
1331
1332     if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(sss)")))
1333     {
1334         g_variant_get (result, "(sss)", language, layout, session);
1335         got_defaults = TRUE;
1336     }
1337
1338     g_variant_unref (result);
1339
1340     return got_defaults;
1341 }
1342
1343 static void
1344 ldm_greeter_init (LdmGreeter *greeter)
1345 {
1346     greeter->priv = G_TYPE_INSTANCE_GET_PRIVATE (greeter, LDM_TYPE_GREETER, LdmGreeterPrivate);
1347     greeter->priv->read_buffer = g_malloc (HEADER_SIZE);
1348
1349     g_debug ("default-language=%s", ldm_greeter_get_default_language (greeter));
1350 }
1351
1352 static void
1353 ldm_greeter_set_property (GObject      *object,
1354                           guint         prop_id,
1355                           const GValue *value,
1356                           GParamSpec   *pspec)
1357 {
1358     LdmGreeter *self;
1359
1360     self = LDM_GREETER (object);
1361
1362     switch (prop_id) {
1363     case PROP_LAYOUT:
1364         ldm_greeter_set_layout(self, g_value_get_string (value));
1365         break;
1366     default:
1367         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1368         break;
1369     }
1370 }
1371
1372 static void
1373 ldm_greeter_get_property (GObject    *object,
1374                           guint       prop_id,
1375                           GValue     *value,
1376                           GParamSpec *pspec)
1377 {
1378     LdmGreeter *self;
1379
1380     self = LDM_GREETER (object);
1381
1382     switch (prop_id) {
1383     case PROP_HOSTNAME:
1384         g_value_set_string (value, ldm_greeter_get_hostname (self));
1385         break;
1386     case PROP_NUM_USERS:
1387         g_value_set_int (value, ldm_greeter_get_num_users (self));
1388         break;
1389     case PROP_USERS:
1390         break;
1391     case PROP_DEFAULT_LANGUAGE:
1392         g_value_set_string (value, ldm_greeter_get_default_language (self));
1393         break;
1394     case PROP_LAYOUTS:
1395         break;
1396     case PROP_LAYOUT:
1397         g_value_set_string (value, ldm_greeter_get_layout (self));
1398         break;
1399     case PROP_SESSIONS:
1400         break;
1401     case PROP_DEFAULT_SESSION:
1402         g_value_set_string (value, ldm_greeter_get_default_session (self));
1403         break;
1404     case PROP_TIMED_LOGIN_USER:
1405         g_value_set_string (value, ldm_greeter_get_timed_login_user (self));
1406         break;
1407     case PROP_TIMED_LOGIN_DELAY:
1408         g_value_set_int (value, ldm_greeter_get_timed_login_delay (self));
1409         break;
1410     case PROP_AUTHENTICATION_USER:
1411         g_value_set_string (value, ldm_greeter_get_authentication_user (self));
1412         break;
1413     case PROP_IN_AUTHENTICATION:
1414         g_value_set_boolean (value, ldm_greeter_get_in_authentication (self));
1415         break;
1416     case PROP_IS_AUTHENTICATED:
1417         g_value_set_boolean (value, ldm_greeter_get_is_authenticated (self));
1418         break;
1419     case PROP_CAN_SUSPEND:
1420         g_value_set_boolean (value, ldm_greeter_get_can_suspend (self));
1421         break;
1422     case PROP_CAN_HIBERNATE:
1423         g_value_set_boolean (value, ldm_greeter_get_can_hibernate (self));
1424         break;
1425     case PROP_CAN_RESTART:
1426         g_value_set_boolean (value, ldm_greeter_get_can_restart (self));
1427         break;
1428     case PROP_CAN_SHUTDOWN:
1429         g_value_set_boolean (value, ldm_greeter_get_can_shutdown (self));
1430         break;
1431     default:
1432         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1433         break;
1434     }
1435 }
1436
1437 static void
1438 ldm_greeter_class_init (LdmGreeterClass *klass)
1439 {
1440     GObjectClass *object_class = G_OBJECT_CLASS (klass);
1441
1442     g_type_class_add_private (klass, sizeof (LdmGreeterPrivate));
1443
1444     object_class->set_property = ldm_greeter_set_property;
1445     object_class->get_property = ldm_greeter_get_property;
1446
1447     g_object_class_install_property (object_class,
1448                                      PROP_NUM_USERS,
1449                                      g_param_spec_string ("hostname",
1450                                                           "hostname",
1451                                                           "Hostname displaying greeter for",
1452                                                           NULL,
1453                                                           G_PARAM_READABLE));
1454     g_object_class_install_property (object_class,
1455                                      PROP_NUM_USERS,
1456                                      g_param_spec_int ("num-users",
1457                                                        "num-users",
1458                                                        "Number of login users",
1459                                                        0, G_MAXINT, 0,
1460                                                        G_PARAM_READABLE));
1461     /*g_object_class_install_property (object_class,
1462                                      PROP_USERS,
1463                                      g_param_spec_list ("users",
1464                                                         "users",
1465                                                         "Users that can login"));
1466     g_object_class_install_property (object_class,
1467                                      PROP_DEFAULT_LANGUAGE,
1468                                      g_param_spec_string ("default-language",
1469                                                           "default-language",
1470                                                           "Default language",
1471                                                           NULL,
1472                                                           G_PARAM_READWRITE));
1473     g_object_class_install_property (object_class,
1474                                      PROP_LAYOUTS,
1475                                      g_param_spec_list ("layouts",
1476                                                         "layouts",
1477                                                         "Available keyboard layouts"));*/
1478     g_object_class_install_property (object_class,
1479                                      PROP_LAYOUT,
1480                                      g_param_spec_string ("layout",
1481                                                           "layout",
1482                                                           "Current keyboard layout",
1483                                                           NULL,
1484                                                           G_PARAM_READWRITE));
1485     /*g_object_class_install_property (object_class,
1486                                      PROP_SESSIONS,
1487                                      g_param_spec_list ("sessions",
1488                                                         "sessions",
1489                                                         "Available sessions"));*/
1490     g_object_class_install_property (object_class,
1491                                      PROP_DEFAULT_SESSION,
1492                                      g_param_spec_string ("default-session",
1493                                                           "default-session",
1494                                                           "Default session",
1495                                                           NULL,
1496                                                           G_PARAM_READWRITE));
1497     g_object_class_install_property (object_class,
1498                                      PROP_TIMED_LOGIN_USER,
1499                                      g_param_spec_string ("timed-login-user",
1500                                                           "timed-login-user",
1501                                                           "User to login as when timed expires",
1502                                                           NULL,
1503                                                           G_PARAM_READABLE));
1504     g_object_class_install_property (object_class,
1505                                      PROP_TIMED_LOGIN_DELAY,
1506                                      g_param_spec_int ("login-delay",
1507                                                        "login-delay",
1508                                                        "Number of seconds until logging in as default user",
1509                                                        G_MININT, G_MAXINT, 0,
1510                                                        G_PARAM_READABLE));
1511     g_object_class_install_property (object_class,
1512                                      PROP_AUTHENTICATION_USER,
1513                                      g_param_spec_string ("authentication-user",
1514                                                           "authentication-user",
1515                                                           "The user being authenticated",
1516                                                           NULL,
1517                                                           G_PARAM_READABLE));
1518     g_object_class_install_property (object_class,
1519                                      PROP_IN_AUTHENTICATION,
1520                                      g_param_spec_boolean ("in-authentication",
1521                                                            "in-authentication",
1522                                                            "TRUE if a user is being authenticated",
1523                                                            FALSE,
1524                                                            G_PARAM_READABLE));
1525     g_object_class_install_property (object_class,
1526                                      PROP_IS_AUTHENTICATED,
1527                                      g_param_spec_boolean ("is-authenticated",
1528                                                            "is-authenticated",
1529                                                            "TRUE if the selected user is authenticated",
1530                                                            FALSE,
1531                                                            G_PARAM_READABLE));
1532     g_object_class_install_property (object_class,
1533                                      PROP_CAN_SUSPEND,
1534                                      g_param_spec_boolean ("can-suspend",
1535                                                            "can-suspend",
1536                                                            "TRUE if allowed to suspend the system",
1537                                                            FALSE,
1538                                                            G_PARAM_READABLE));
1539     g_object_class_install_property (object_class,
1540                                      PROP_CAN_HIBERNATE,
1541                                      g_param_spec_boolean ("can-hibernate",
1542                                                            "can-hibernate",
1543                                                            "TRUE if allowed to hibernate the system",
1544                                                            FALSE,
1545                                                            G_PARAM_READABLE));
1546     g_object_class_install_property (object_class,
1547                                      PROP_CAN_RESTART,
1548                                      g_param_spec_boolean ("can-restart",
1549                                                            "can-restart",
1550                                                            "TRUE if allowed to restart the system",
1551                                                            FALSE,
1552                                                            G_PARAM_READABLE));
1553     g_object_class_install_property (object_class,
1554                                      PROP_CAN_SHUTDOWN,
1555                                      g_param_spec_boolean ("can-shutdown",
1556                                                            "can-shutdown",
1557                                                            "TRUE if allowed to shutdown the system",
1558                                                            FALSE,
1559                                                            G_PARAM_READABLE));
1560
1561     /**
1562      * LdmGreeter::connected:
1563      * @greeter: A #LdmGreeter
1564      *
1565      * The ::connected signal gets emitted when the greeter connects to the
1566      * LightDM server.
1567      **/
1568     signals[CONNECTED] =
1569         g_signal_new ("connected",
1570                       G_TYPE_FROM_CLASS (klass),
1571                       G_SIGNAL_RUN_LAST,
1572                       G_STRUCT_OFFSET (LdmGreeterClass, connected),
1573                       NULL, NULL,
1574                       g_cclosure_marshal_VOID__VOID,
1575                       G_TYPE_NONE, 0);
1576
1577     /**
1578      * LdmGreeter::show-prompt:
1579      * @greeter: A #LdmGreeter
1580      * @text: Prompt text
1581      *
1582      * The ::show-prompt signal gets emitted when the greeter should show a
1583      * prompt to the user.  The given text should be displayed and an input
1584      * field for the user to provide a response.
1585      *
1586      * Call ldm_greeter_provide_secret() with the resultant input or
1587      * ldm_greeter_cancel_authentication() to abort the authentication.
1588      **/
1589     signals[SHOW_PROMPT] =
1590         g_signal_new ("show-prompt",
1591                       G_TYPE_FROM_CLASS (klass),
1592                       G_SIGNAL_RUN_LAST,
1593                       G_STRUCT_OFFSET (LdmGreeterClass, show_prompt),
1594                       NULL, NULL,
1595                       g_cclosure_marshal_VOID__STRING,
1596                       G_TYPE_NONE, 1, G_TYPE_STRING);
1597
1598     /**
1599      * LdmGreeter::show-message:
1600      * @greeter: A #LdmGreeter
1601      * @text: Message text
1602      *
1603      * The ::show-message signal gets emitted when the greeter
1604      * should show an informational message to the user.
1605      **/
1606     signals[SHOW_MESSAGE] =
1607         g_signal_new ("show-message",
1608                       G_TYPE_FROM_CLASS (klass),
1609                       G_SIGNAL_RUN_LAST,
1610                       G_STRUCT_OFFSET (LdmGreeterClass, show_message),
1611                       NULL, NULL,
1612                       g_cclosure_marshal_VOID__STRING,
1613                       G_TYPE_NONE, 1, G_TYPE_STRING);
1614
1615     /**
1616      * LdmGreeter::show-error:
1617      * @greeter: A #LdmGreeter
1618      * @text: Message text
1619      *
1620      * The ::show-error signal gets emitted when the greeter
1621      * should show an error message to the user.
1622      **/
1623     signals[SHOW_ERROR] =
1624         g_signal_new ("show-error",
1625                       G_TYPE_FROM_CLASS (klass),
1626                       G_SIGNAL_RUN_LAST,
1627                       G_STRUCT_OFFSET (LdmGreeterClass, show_error),
1628                       NULL, NULL,
1629                       g_cclosure_marshal_VOID__STRING,
1630                       G_TYPE_NONE, 1, G_TYPE_STRING);
1631
1632     /**
1633      * LdmGreeter::authentication-complete:
1634      * @greeter: A #LdmGreeter
1635      *
1636      * The ::authentication-complete signal gets emitted when the greeter
1637      * has completed authentication.
1638      *
1639      * Call ldm_greeter_get_is_authenticated() to check if the authentication
1640      * was successful.
1641      **/
1642     signals[AUTHENTICATION_COMPLETE] =
1643         g_signal_new ("authentication-complete",
1644                       G_TYPE_FROM_CLASS (klass),
1645                       G_SIGNAL_RUN_LAST,
1646                       G_STRUCT_OFFSET (LdmGreeterClass, authentication_complete),
1647                       NULL, NULL,
1648                       g_cclosure_marshal_VOID__VOID,
1649                       G_TYPE_NONE, 0);
1650
1651     /**
1652      * LdmGreeter::timed-login:
1653      * @greeter: A #LdmGreeter
1654      * @username: A username
1655      *
1656      * The ::timed-login signal gets emitted when the default user timer
1657      * has expired.
1658      **/
1659     signals[TIMED_LOGIN] =
1660         g_signal_new ("timed-login",
1661                       G_TYPE_FROM_CLASS (klass),
1662                       G_SIGNAL_RUN_LAST,
1663                       G_STRUCT_OFFSET (LdmGreeterClass, timed_login),
1664                       NULL, NULL,
1665                       g_cclosure_marshal_VOID__STRING,
1666                       G_TYPE_NONE, 1, G_TYPE_STRING);
1667
1668     /**
1669      * LdmGreeter::quit:
1670      * @greeter: A #LdmGreeter
1671      *
1672      * The ::quit signal gets emitted when the greeter should exit.
1673      **/
1674     signals[QUIT] =
1675         g_signal_new ("quit",
1676                       G_TYPE_FROM_CLASS (klass),
1677                       G_SIGNAL_RUN_LAST,
1678                       G_STRUCT_OFFSET (LdmGreeterClass, quit),
1679                       NULL, NULL,
1680                       g_cclosure_marshal_VOID__VOID,
1681                       G_TYPE_NONE, 0);
1682 }