Home | History | Annotate | Download | only in gio
      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 (at) 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"
    666