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