Add support for abstract unix socket addresses
[platform/upstream/glib.git] / gio / gmountoperation.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include "config.h"
24
25 #include <string.h>
26
27 #include "gmountoperation.h"
28 #include "gioenumtypes.h"
29 #include "gio-marshal.h"
30 #include "glibintl.h"
31
32 #include "gioalias.h"
33
34 /** 
35  * SECTION:gmountoperation
36  * @short_description: Authentication methods for mountable locations
37  * @include: gio/gio.h
38  *
39  * #GMountOperation provides a mechanism for authenticating mountable 
40  * operations, such as loop mounting files, hard drive partitions or 
41  * server locations. 
42  *
43  * Mounting operations are handed a #GMountOperation that then can use 
44  * if they require any privileges or authentication for their volumes 
45  * to be mounted (e.g. a hard disk partition or an encrypted filesystem), 
46  * or if they are implementing a remote server protocol which requires 
47  * user credentials such as FTP or WebDAV.
48  *
49  * Users should instantiate a subclass of this that implements all
50  * the various callbacks to show the required dialogs, such as 
51  * #GtkMountOperation.
52  **/
53
54 G_DEFINE_TYPE (GMountOperation, g_mount_operation, G_TYPE_OBJECT);
55
56 enum {
57   ASK_PASSWORD,
58   ASK_QUESTION,
59   REPLY,
60   ABORTED,
61   LAST_SIGNAL
62 };
63
64 static guint signals[LAST_SIGNAL] = { 0 };
65
66 struct _GMountOperationPrivate {
67   char *password;
68   char *user;
69   char *domain;
70   gboolean anonymous;
71   GPasswordSave password_save;
72   int choice;
73 };
74
75 enum {
76   PROP_0,
77   PROP_USERNAME,
78   PROP_PASSWORD,
79   PROP_ANONYMOUS,
80   PROP_DOMAIN,
81   PROP_PASSWORD_SAVE,
82   PROP_CHOICE
83 };
84
85 static void 
86 g_mount_operation_set_property (GObject      *object,
87                                 guint         prop_id,
88                                 const GValue *value,
89                                 GParamSpec   *pspec)
90 {
91   GMountOperation *operation;
92
93   operation = G_MOUNT_OPERATION (object);
94
95   switch (prop_id)
96     {
97     case PROP_USERNAME:
98       g_mount_operation_set_username (operation, 
99                                       g_value_get_string (value));
100       break;
101    
102     case PROP_PASSWORD:
103       g_mount_operation_set_password (operation, 
104                                       g_value_get_string (value));
105       break;
106
107     case PROP_ANONYMOUS:
108       g_mount_operation_set_anonymous (operation, 
109                                        g_value_get_boolean (value));
110       break;
111
112     case PROP_DOMAIN:
113       g_mount_operation_set_domain (operation, 
114                                     g_value_get_string (value));
115       break;
116
117     case PROP_PASSWORD_SAVE:
118       g_mount_operation_set_password_save (operation, 
119                                            g_value_get_enum (value));
120       break;
121
122     case PROP_CHOICE:
123       g_mount_operation_set_choice (operation, 
124                                     g_value_get_int (value));
125       break;
126
127     default:
128       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
129       break;
130     }
131 }
132
133
134 static void 
135 g_mount_operation_get_property (GObject    *object,
136                                 guint       prop_id,
137                                 GValue     *value,
138                                 GParamSpec *pspec)
139 {
140   GMountOperation *operation;
141   GMountOperationPrivate *priv;
142
143   operation = G_MOUNT_OPERATION (object);
144   priv = operation->priv;
145   
146   switch (prop_id)
147     {
148     case PROP_USERNAME:
149       g_value_set_string (value, priv->user);
150       break;
151
152     case PROP_PASSWORD:
153       g_value_set_string (value, priv->password);
154       break;
155
156     case PROP_ANONYMOUS:
157       g_value_set_boolean (value, priv->anonymous);
158       break;
159
160     case PROP_DOMAIN:
161       g_value_set_string (value, priv->domain);
162       break;
163
164     case PROP_PASSWORD_SAVE:
165       g_value_set_enum (value, priv->password_save);
166       break;
167
168     case PROP_CHOICE:
169       g_value_set_int (value, priv->choice);
170       break;
171
172     default:
173       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
174       break;
175     }
176 }
177
178
179 static void
180 g_mount_operation_finalize (GObject *object)
181 {
182   GMountOperation *operation;
183   GMountOperationPrivate *priv;
184
185   operation = G_MOUNT_OPERATION (object);
186
187   priv = operation->priv;
188   
189   g_free (priv->password);
190   g_free (priv->user);
191   g_free (priv->domain);
192
193   G_OBJECT_CLASS (g_mount_operation_parent_class)->finalize (object);
194 }
195
196 static gboolean
197 reply_non_handled_in_idle (gpointer data)
198 {
199   GMountOperation *op = data;
200
201   g_mount_operation_reply (op, G_MOUNT_OPERATION_UNHANDLED);
202   return FALSE;
203 }
204
205 static void
206 ask_password (GMountOperation *op,
207               const char      *message,
208               const char      *default_user,
209               const char      *default_domain,
210               GAskPasswordFlags flags)
211 {
212   g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
213                    reply_non_handled_in_idle,
214                    g_object_ref (op),
215                    g_object_unref);
216 }
217   
218 static void
219 ask_question (GMountOperation *op,
220               const char      *message,
221               const char      *choices[])
222 {
223   g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
224                    reply_non_handled_in_idle,
225                    g_object_ref (op),
226                    g_object_unref);
227 }
228
229 static void
230 g_mount_operation_class_init (GMountOperationClass *klass)
231 {
232   GObjectClass *object_class;
233   
234   g_type_class_add_private (klass, sizeof (GMountOperationPrivate));
235  
236   object_class = G_OBJECT_CLASS (klass);
237   object_class->finalize = g_mount_operation_finalize;
238   object_class->get_property = g_mount_operation_get_property;
239   object_class->set_property = g_mount_operation_set_property;
240   
241   klass->ask_password = ask_password;
242   klass->ask_question = ask_question;
243   
244   /**
245    * GMountOperation::ask-password:
246    * @op: a #GMountOperation requesting a password.
247    * @message: string containing a message to display to the user.
248    * @default_user: string containing the default user name.
249    * @default_domain: string containing the default domain.
250    * @flags: a set of #GAskPasswordFlags.
251    *
252    * Emitted when a mount operation asks the user for a password.
253    *
254    * If the message contains a line break, the first line should be
255    * presented as a heading. For example, it may be used as the
256    * primary text in a #GtkMessageDialog.
257    */
258   signals[ASK_PASSWORD] =
259     g_signal_new (I_("ask-password"),
260                   G_TYPE_FROM_CLASS (object_class),
261                   G_SIGNAL_RUN_LAST,
262                   G_STRUCT_OFFSET (GMountOperationClass, ask_password),
263                   NULL, NULL,
264                   _gio_marshal_VOID__STRING_STRING_STRING_FLAGS,
265                   G_TYPE_NONE, 4,
266                   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_ASK_PASSWORD_FLAGS);
267                   
268   /**
269    * GMountOperation::ask-question:
270    * @op: a #GMountOperation asking a question.
271    * @message: string containing a message to display to the user.
272    * @choices: an array of strings for each possible choice.
273    *
274    * Emitted when asking the user a question and gives a list of
275    * choices for the user to choose from.
276    *
277    * If the message contains a line break, the first line should be
278    * presented as a heading. For example, it may be used as the
279    * primary text in a #GtkMessageDialog.
280    */
281   signals[ASK_QUESTION] =
282     g_signal_new (I_("ask-question"),
283                   G_TYPE_FROM_CLASS (object_class),
284                   G_SIGNAL_RUN_LAST,
285                   G_STRUCT_OFFSET (GMountOperationClass, ask_question),
286                   NULL, NULL,
287                   _gio_marshal_VOID__STRING_BOXED,
288                   G_TYPE_NONE, 2,
289                   G_TYPE_STRING, G_TYPE_STRV);
290                   
291   /**
292    * GMountOperation::reply:
293    * @op: a #GMountOperation.
294    * @result: a #GMountOperationResult indicating how the request was handled
295    *
296    * Emitted when the user has replied to the mount operation.
297    */
298   signals[REPLY] =
299     g_signal_new (I_("reply"),
300                   G_TYPE_FROM_CLASS (object_class),
301                   G_SIGNAL_RUN_LAST,
302                   G_STRUCT_OFFSET (GMountOperationClass, reply),
303                   NULL, NULL,
304                   g_cclosure_marshal_VOID__ENUM,
305                   G_TYPE_NONE, 1,
306                   G_TYPE_MOUNT_OPERATION_RESULT);
307
308   /**
309    * GMountOperation::aborted:
310    *
311    * Emitted by the backend when e.g. a device becomes unavailable
312    * while a mount operation is in progress.
313    *
314    * Implementations of GMountOperation should handle this signal
315    * by dismissing open password dialogs.
316    *
317    * Since: 2.20
318    */
319   signals[ABORTED] =
320     g_signal_new (I_("aborted"),
321                   G_TYPE_FROM_CLASS (object_class),
322                   G_SIGNAL_RUN_LAST,
323                   G_STRUCT_OFFSET (GMountOperationClass, aborted),
324                   NULL, NULL,
325                   g_cclosure_marshal_VOID__VOID,
326                   G_TYPE_NONE, 0);
327
328   /**
329    * GMountOperation:username:
330    *
331    * The user name that is used for authentication when carrying out
332    * the mount operation.
333    */ 
334   g_object_class_install_property (object_class,
335                                    PROP_USERNAME,
336                                    g_param_spec_string ("username",
337                                                         P_("Username"),
338                                                         P_("The user name"),
339                                                         NULL,
340                                                         G_PARAM_READWRITE|
341                                                         G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
342
343   /**
344    * GMountOperation:password:
345    *
346    * The password that is used for authentication when carrying out
347    * the mount operation.
348    */ 
349   g_object_class_install_property (object_class,
350                                    PROP_PASSWORD,
351                                    g_param_spec_string ("password",
352                                                         P_("Password"),
353                                                         P_("The password"),
354                                                         NULL,
355                                                         G_PARAM_READWRITE|
356                                                         G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
357
358   /**
359    * GMountOperation:anonymous:
360    * 
361    * Whether to use an anonymous user when authenticating.
362    */
363   g_object_class_install_property (object_class,
364                                    PROP_ANONYMOUS,
365                                    g_param_spec_boolean ("anonymous",
366                                                          P_("Anonymous"),
367                                                          P_("Whether to use an anonymous user"),
368                                                          FALSE,
369                                                          G_PARAM_READWRITE|
370                                                          G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
371
372   /**
373    * GMountOperation:domain:
374    *
375    * The domain to use for the mount operation.
376    */ 
377   g_object_class_install_property (object_class,
378                                    PROP_DOMAIN,
379                                    g_param_spec_string ("domain",
380                                                         P_("Domain"),
381                                                         P_("The domain of the mount operation"),
382                                                         NULL,
383                                                         G_PARAM_READWRITE|
384                                                         G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
385
386   /**
387    * GMountOperation:password-save:
388    *
389    * Determines if and how the password information should be saved. 
390    */ 
391   g_object_class_install_property (object_class,
392                                    PROP_PASSWORD_SAVE,
393                                    g_param_spec_enum ("password-save",
394                                                       P_("Password save"),
395                                                       P_("How passwords should be saved"),
396                                                       G_TYPE_PASSWORD_SAVE,
397                                                       G_PASSWORD_SAVE_NEVER,
398                                                       G_PARAM_READWRITE|
399                                                       G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
400
401   /**
402    * GMountOperation:choice:
403    *
404    * The index of the user's choice when a question is asked during the 
405    * mount operation. See the #GMountOperation::ask-question signal.
406    */ 
407   g_object_class_install_property (object_class,
408                                    PROP_CHOICE,
409                                    g_param_spec_int ("choice",
410                                                      P_("Choice"),
411                                                      P_("The users choice"),
412                                                      0, G_MAXINT, 0,
413                                                      G_PARAM_READWRITE|
414                                                      G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
415 }
416
417 static void
418 g_mount_operation_init (GMountOperation *operation)
419 {
420   operation->priv = G_TYPE_INSTANCE_GET_PRIVATE (operation,
421                                                  G_TYPE_MOUNT_OPERATION,
422                                                  GMountOperationPrivate);
423 }
424
425 /**
426  * g_mount_operation_new:
427  * 
428  * Creates a new mount operation.
429  * 
430  * Returns: a #GMountOperation.
431  **/
432 GMountOperation *
433 g_mount_operation_new (void)
434 {
435   return g_object_new (G_TYPE_MOUNT_OPERATION, NULL);
436 }
437
438 /**
439  * g_mount_operation_get_username
440  * @op: a #GMountOperation.
441  * 
442  * Get the user name from the mount operation.
443  *
444  * Returns: a string containing the user name.
445  **/
446 const char *
447 g_mount_operation_get_username (GMountOperation *op)
448 {
449   g_return_val_if_fail (G_IS_MOUNT_OPERATION (op), NULL);
450   return op->priv->user;
451 }
452
453 /**
454  * g_mount_operation_set_username:
455  * @op: a #GMountOperation.
456  * @username: input username.
457  *
458  * Sets the user name within @op to @username.
459  **/
460 void
461 g_mount_operation_set_username (GMountOperation *op,
462                                 const char      *username)
463 {
464   g_return_if_fail (G_IS_MOUNT_OPERATION (op));
465   g_free (op->priv->user);
466   op->priv->user = g_strdup (username);
467   g_object_notify (G_OBJECT (op), "username");
468 }
469
470 /**
471  * g_mount_operation_get_password:
472  * @op: a #GMountOperation.
473  *
474  * Gets a password from the mount operation. 
475  *
476  * Returns: a string containing the password within @op.
477  **/
478 const char *
479 g_mount_operation_get_password (GMountOperation *op)
480 {
481   g_return_val_if_fail (G_IS_MOUNT_OPERATION (op), NULL);
482   return op->priv->password;
483 }
484
485 /**
486  * g_mount_operation_set_password:
487  * @op: a #GMountOperation.
488  * @password: password to set.
489  * 
490  * Sets the mount operation's password to @password.  
491  *
492  **/
493 void
494 g_mount_operation_set_password (GMountOperation *op,
495                                 const char      *password)
496 {
497   g_return_if_fail (G_IS_MOUNT_OPERATION (op));
498   g_free (op->priv->password);
499   op->priv->password = g_strdup (password);
500   g_object_notify (G_OBJECT (op), "password");
501 }
502
503 /**
504  * g_mount_operation_get_anonymous:
505  * @op: a #GMountOperation.
506  * 
507  * Check to see whether the mount operation is being used 
508  * for an anonymous user.
509  * 
510  * Returns: %TRUE if mount operation is anonymous. 
511  **/
512 gboolean
513 g_mount_operation_get_anonymous (GMountOperation *op)
514 {
515   g_return_val_if_fail (G_IS_MOUNT_OPERATION (op), FALSE);
516   return op->priv->anonymous;
517 }
518
519 /**
520  * g_mount_operation_set_anonymous:
521  * @op: a #GMountOperation.
522  * @anonymous: boolean value.
523  * 
524  * Sets the mount operation to use an anonymous user if @anonymous is %TRUE.
525  **/  
526 void
527 g_mount_operation_set_anonymous (GMountOperation *op,
528                                  gboolean         anonymous)
529 {
530   GMountOperationPrivate *priv;
531   g_return_if_fail (G_IS_MOUNT_OPERATION (op));
532   priv = op->priv;
533
534   if (priv->anonymous != anonymous)
535     {
536       priv->anonymous = anonymous;
537       g_object_notify (G_OBJECT (op), "anonymous");
538     }
539 }
540
541 /**
542  * g_mount_operation_get_domain:
543  * @op: a #GMountOperation.
544  * 
545  * Gets the domain of the mount operation.
546  * 
547  * Returns: a string set to the domain. 
548  **/
549 const char *
550 g_mount_operation_get_domain (GMountOperation *op)
551 {
552   g_return_val_if_fail (G_IS_MOUNT_OPERATION (op), NULL);
553   return op->priv->domain;
554 }
555
556 /**
557  * g_mount_operation_set_domain:
558  * @op: a #GMountOperation.
559  * @domain: the domain to set.
560  * 
561  * Sets the mount operation's domain. 
562  **/  
563 void
564 g_mount_operation_set_domain (GMountOperation *op,
565                               const char      *domain)
566 {
567   g_return_if_fail (G_IS_MOUNT_OPERATION (op));
568   g_free (op->priv->domain);
569   op->priv->domain = g_strdup (domain);
570   g_object_notify (G_OBJECT (op), "domain");
571 }
572
573 /**
574  * g_mount_operation_get_password_save:
575  * @op: a #GMountOperation.
576  * 
577  * Gets the state of saving passwords for the mount operation.
578  *
579  * Returns: a #GPasswordSave flag. 
580  **/  
581
582 GPasswordSave
583 g_mount_operation_get_password_save (GMountOperation *op)
584 {
585   g_return_val_if_fail (G_IS_MOUNT_OPERATION (op), G_PASSWORD_SAVE_NEVER);
586   return op->priv->password_save;
587 }
588
589 /**
590  * g_mount_operation_set_password_save:
591  * @op: a #GMountOperation.
592  * @save: a set of #GPasswordSave flags.
593  * 
594  * Sets the state of saving passwords for the mount operation.
595  * 
596  **/   
597 void
598 g_mount_operation_set_password_save (GMountOperation *op,
599                                      GPasswordSave    save)
600 {
601   GMountOperationPrivate *priv;
602   g_return_if_fail (G_IS_MOUNT_OPERATION (op));
603   priv = op->priv;
604  
605   if (priv->password_save != save)
606     {
607       priv->password_save = save;
608       g_object_notify (G_OBJECT (op), "password-save");
609     }
610 }
611
612 /**
613  * g_mount_operation_get_choice:
614  * @op: a #GMountOperation.
615  * 
616  * Gets a choice from the mount operation.
617  *
618  * Returns: an integer containing an index of the user's choice from 
619  * the choice's list, or %0.
620  **/
621 int
622 g_mount_operation_get_choice (GMountOperation *op)
623 {
624   g_return_val_if_fail (G_IS_MOUNT_OPERATION (op), 0);
625   return op->priv->choice;
626 }
627
628 /**
629  * g_mount_operation_set_choice:
630  * @op: a #GMountOperation.
631  * @choice: an integer.
632  *
633  * Sets a default choice for the mount operation.
634  **/
635 void
636 g_mount_operation_set_choice (GMountOperation *op,
637                               int              choice)
638 {
639   GMountOperationPrivate *priv;
640   g_return_if_fail (G_IS_MOUNT_OPERATION (op));
641   priv = op->priv;
642   if (priv->choice != choice)
643     {
644       priv->choice = choice;
645       g_object_notify (G_OBJECT (op), "choice");
646     }
647 }
648
649 /**
650  * g_mount_operation_reply:
651  * @op: a #GMountOperation
652  * @result: a #GMountOperationResult
653  * 
654  * Emits the #GMountOperation::reply signal.
655  **/
656 void
657 g_mount_operation_reply (GMountOperation *op,
658                          GMountOperationResult result)
659 {
660   g_return_if_fail (G_IS_MOUNT_OPERATION (op));
661   g_signal_emit (op, signals[REPLY], 0, result);
662 }
663
664 #define __G_MOUNT_OPERATION_C__
665 #include "gioaliasdef.c"