~noskcaj/ubuntu/vivid/gnome-keyring/3.15.90

« back to all changes in this revision

Viewing changes to gcr/gcr-importer.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach
  • Date: 2012-05-14 22:13:02 UTC
  • mfrom: (1.3.1)
  • mto: (80.2.8 experimental) (1.1.77)
  • mto: This revision was merged to the branch mainline in revision 148.
  • Revision ID: package-import@ubuntu.com-20120514221302-0l3gjmqpe6xopond
ImportĀ upstreamĀ versionĀ 3.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
 * gnome-keyring
3
 
 * 
4
 
 * Copyright (C) 2008 Stefan Walter
5
 
 * 
6
 
 * This program is free software; you can redistribute it and/or modify 
7
 
 * it under the terms of the GNU Lesser General Public License as
8
 
 * published by the Free Software Foundation; either version 2.1 of
9
 
 * the License, or (at your option) any later version.
10
 
 *  
11
 
 * This program is distributed in the hope that it will be useful, but
12
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *  
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19
 
 * 02111-1307, USA.  
20
 
 */
21
 
 
22
 
#include "config.h"
23
 
 
24
 
#include "gcr-import-dialog.h"
25
 
#include "gcr-importer.h"
26
 
#include "gcr-internal.h"
27
 
#include "gcr-marshal.h"
28
 
#include "gcr-parser.h"
29
 
 
30
 
#include <glib/gi18n-lib.h>
31
 
 
32
 
enum {
33
 
        PROP_0,
34
 
        PROP_SLOT,
35
 
        PROP_PROMPT_BEHAVIOR
36
 
};
37
 
 
38
 
enum {
39
 
        QUEUED,
40
 
        IMPORTED,
41
 
        LAST_SIGNAL
42
 
};
43
 
 
44
 
static guint signals[LAST_SIGNAL] = { 0 };
45
 
 
46
 
struct _GcrImporterPrivate {
47
 
        GckSlot *slot;
48
 
        GcrParser *parser;
49
 
        GcrImporterPromptBehavior behavior;
50
 
        
51
 
        /* Information about last import */
52
 
        GError *error;
53
 
        gboolean succeeded;
54
 
        
55
 
        /* State data during import */
56
 
        gboolean processing;
57
 
        GCancellable *cancel;
58
 
        gboolean prompted;
59
 
        gboolean async;
60
 
        GByteArray *buffer;
61
 
        GckSession *session;
62
 
        GQueue queue;
63
 
 
64
 
        /* Extra async stuff */
65
 
        GAsyncReadyCallback callback;
66
 
        gpointer user_data;
67
 
};
68
 
 
69
 
/* State forward declarations */
70
 
static void state_cancelled (GcrImporter *self, gboolean async);
71
 
static void state_complete (GcrImporter *self, gboolean async);
72
 
static void state_create_object (GcrImporter *self, gboolean async);
73
 
static void state_open_session (GcrImporter *self, gboolean async);
74
 
static void state_initialize_pin (GcrImporter *self, gboolean async);
75
 
 
76
 
static void gcr_importer_async_result (GAsyncResultIface *iface);
77
 
G_DEFINE_TYPE_WITH_CODE (GcrImporter, gcr_importer, G_TYPE_OBJECT,
78
 
                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, gcr_importer_async_result));
79
 
 
80
 
#define BLOCK 4096
81
 
 
82
 
/* -----------------------------------------------------------------------------
83
 
 * INTERNAL 
84
 
 */
85
 
 
86
 
static void
87
 
cleanup_state_data (GcrImporter *self)
88
 
{
89
 
        GckAttributes *attrs;
90
 
 
91
 
        if (self->pv->buffer)
92
 
                g_byte_array_free (self->pv->buffer, TRUE);
93
 
        self->pv->buffer = NULL;
94
 
 
95
 
        if (self->pv->session)
96
 
                g_object_unref (self->pv->session);
97
 
        self->pv->session = NULL;
98
 
        
99
 
        while ((attrs = g_queue_pop_head (&self->pv->queue)) != NULL)
100
 
                gck_attributes_unref (attrs);
101
 
        g_assert (g_queue_is_empty (&self->pv->queue));
102
 
 
103
 
        if (self->pv->cancel)
104
 
                g_object_unref (self->pv->cancel);
105
 
        self->pv->cancel = NULL;
106
 
}
107
 
 
108
 
static void
109
 
cleanup_import_data (GcrImporter *self)
110
 
{
111
 
        if (self->pv->error)
112
 
                g_clear_error (&self->pv->error);
113
 
        self->pv->succeeded = TRUE;
114
 
}
115
 
 
116
 
static void
117
 
next_state (GcrImporter *self, void (*state) (GcrImporter*, gboolean))
118
 
{
119
 
        g_assert (GCR_IS_IMPORTER (self));
120
 
        g_assert (self->pv->processing);
121
 
        g_assert (state);
122
 
        
123
 
        if (self->pv->cancel && g_cancellable_is_cancelled (self->pv->cancel))
124
 
                state = state_cancelled;
125
 
        
126
 
        (state) (self, self->pv->async);
127
 
}
128
 
 
129
 
static const gchar*
130
 
prepare_auth_primary (CK_OBJECT_CLASS klass)
131
 
{
132
 
        if (klass == CKO_PRIVATE_KEY)
133
 
                return _("Enter password to unlock the private key");
134
 
        else if (klass == CKO_CERTIFICATE)
135
 
                return _("Enter password to unlock the certificate");
136
 
        else
137
 
                return _("Enter password to unlock");
138
 
}
139
 
 
140
 
static gchar*
141
 
prepare_auth_secondary (CK_OBJECT_CLASS klass, const gchar *label)
142
 
{
143
 
        if (label == NULL) {
144
 
                if (klass == CKO_PRIVATE_KEY) {
145
 
                        /* TRANSLATORS: The key is locked. */
146
 
                        return g_strdup (_("In order to import the private key, it must be unlocked"));
147
 
                } else if (klass == CKO_CERTIFICATE) {
148
 
                        /* TRANSLATORS: The certificate is locked. */
149
 
                        return g_strdup (_("In order to import the certificate, it must be unlocked"));
150
 
                } else {
151
 
                        /* TRANSLATORS: The data is locked. */
152
 
                        return g_strdup (_("In order to import the data, it must be unlocked"));
153
 
                }
154
 
        } else {
155
 
                if (klass == CKO_PRIVATE_KEY) {
156
 
                        /* TRANSLATORS: The key is locked. */
157
 
                        return g_strdup_printf (_("In order to import the private key '%s', it must be unlocked"), label);
158
 
                } else if (klass == CKO_CERTIFICATE) {
159
 
                        /* TRANSLATORS: The certificate is locked. */
160
 
                        return g_strdup_printf (_("In order to import the certificate '%s', it must be unlocked"), label);
161
 
                } else {
162
 
                        /* TRANSLATORS: The object '%s' is locked. */
163
 
                        return g_strdup_printf (_("In order to import '%s', it must be unlocked"), label);
164
 
                }
165
 
        }
166
 
}
167
 
 
168
 
static void
169
 
on_parser_parsed (GcrParser *parser, GcrImporter *self)
170
 
{
171
 
        GckAttributes *attrs;
172
 
 
173
 
        g_return_if_fail (GCR_IS_PARSER (parser));
174
 
        g_return_if_fail (GCR_IS_IMPORTER (self));
175
 
 
176
 
        attrs = gcr_parser_get_parsed_attributes (parser);
177
 
        g_return_if_fail (attrs);
178
 
 
179
 
        gcr_importer_queue (self, gcr_parser_get_parsed_label (parser), attrs);
180
 
}
181
 
 
182
 
static gboolean
183
 
on_parser_authenticate (GcrParser *parser, gint count, GcrImporter *self)
184
 
{
185
 
        GcrImportDialog *dialog;
186
 
        GckAttributes *attrs;
187
 
        const gchar *password;
188
 
        gchar *text, *label;
189
 
        GckSlot *slot;
190
 
        gulong klass;
191
 
 
192
 
        dialog = _gcr_import_dialog_new ();
193
 
 
194
 
        if (self->pv->slot)
195
 
                _gcr_import_dialog_set_selected_slot (dialog, self->pv->slot);
196
 
 
197
 
        /* Figure out the text for the dialog */
198
 
        attrs = gcr_parser_get_parsed_attributes (parser);
199
 
        g_return_val_if_fail (attrs, FALSE);
200
 
 
201
 
        if (!gck_attributes_find_ulong (attrs, CKA_CLASS, &klass))
202
 
                klass = (gulong)-1;
203
 
        if (!gck_attributes_find_string (attrs, CKA_LABEL, &label))
204
 
                label = NULL;
205
 
 
206
 
        text = prepare_auth_secondary (klass, label);
207
 
        _gcr_import_dialog_set_primary_text (dialog, prepare_auth_primary (klass));
208
 
        _gcr_import_dialog_set_secondary_text (dialog, text);
209
 
        g_free (label);
210
 
        g_free (text);
211
 
 
212
 
        if (!_gcr_import_dialog_run (dialog, NULL))
213
 
                return FALSE;
214
 
 
215
 
        slot = _gcr_import_dialog_get_selected_slot (dialog);
216
 
        gcr_importer_set_slot (self, slot);
217
 
 
218
 
        password = _gcr_import_dialog_get_password (dialog);
219
 
        gcr_parser_add_password (parser, password);
220
 
 
221
 
        g_object_unref (dialog);
222
 
        self->pv->prompted = TRUE;
223
 
        return TRUE;
224
 
}
225
 
 
226
 
/* ---------------------------------------------------------------------------------
227
 
 * COMPLETE
228
 
 */
229
 
 
230
 
static void
231
 
state_complete (GcrImporter *self, gboolean async)
232
 
{
233
 
        if (async && self->pv->callback != NULL)
234
 
                (self->pv->callback) (G_OBJECT (self), G_ASYNC_RESULT (self), self->pv->user_data);
235
 
        
236
 
        cleanup_state_data (self);
237
 
        self->pv->processing = FALSE;
238
 
}
239
 
 
240
 
static void
241
 
state_failure (GcrImporter *self, gboolean async)
242
 
{
243
 
        self->pv->succeeded = FALSE;
244
 
        next_state (self, state_complete);
245
 
}
246
 
 
247
 
static void
248
 
state_cancelled (GcrImporter *self, gboolean async)
249
 
{
250
 
        if (self->pv->cancel && g_cancellable_is_cancelled (self->pv->cancel))
251
 
                g_cancellable_cancel (self->pv->cancel);
252
 
        if (self->pv->error)
253
 
                g_error_free (self->pv->error);
254
 
        self->pv->error = g_error_new_literal (GCR_DATA_ERROR, GCR_ERROR_CANCELLED, _("The operation was cancelled"));
255
 
        next_state (self, state_failure);
256
 
}
257
 
 
258
 
/* ---------------------------------------------------------------------------------
259
 
 * CREATE OBJECTS
260
 
 */
261
 
 
262
 
static void
263
 
complete_create_object (GcrImporter *self, GckObject *object, GError *error)
264
 
{
265
 
        if (object == NULL) {
266
 
                g_propagate_error (&self->pv->error, error);
267
 
                next_state (self, state_failure);
268
 
                
269
 
        } else {
270
 
                g_signal_emit (self, signals[IMPORTED], 0, object);
271
 
                g_object_unref (object);
272
 
                next_state (self, state_create_object);
273
 
        }
274
 
}
275
 
 
276
 
static void
277
 
on_create_object (GObject *obj, GAsyncResult *res, gpointer user_data)
278
 
{
279
 
        GError *error = NULL;
280
 
        GckObject *object = gck_session_create_object_finish (GCK_SESSION (obj), res, &error);
281
 
        complete_create_object (GCR_IMPORTER (user_data), object, error);
282
 
}
283
 
 
284
 
static void
285
 
state_create_object (GcrImporter *self, gboolean async)
286
 
{
287
 
        GckAttributes *attrs;
288
 
        GckObject *object;
289
 
        GError *error = NULL;
290
 
        
291
 
        /* No more objects */
292
 
        if (g_queue_is_empty (&self->pv->queue)) {
293
 
                next_state (self, state_complete);
294
 
                
295
 
        } else {
296
 
                
297
 
                /* Pop first one off the list */
298
 
                attrs = g_queue_pop_head (&self->pv->queue);
299
 
                g_assert (attrs);
300
 
 
301
 
                gck_attributes_add_boolean (attrs, CKA_TOKEN, CK_TRUE);
302
 
 
303
 
                if (async) {
304
 
                        gck_session_create_object_async (self->pv->session, attrs, self->pv->cancel,
305
 
                                                          on_create_object, self);
306
 
                } else {
307
 
                        object = gck_session_create_object (self->pv->session, attrs, self->pv->cancel, &error);
308
 
                        complete_create_object (self, object, error);
309
 
                }
310
 
        
311
 
                gck_attributes_unref (attrs);
312
 
        }
313
 
}
314
 
 
315
 
/* ---------------------------------------------------------------------------------
316
 
 * OPEN SESSION
317
 
 */
318
 
 
319
 
static void
320
 
complete_open_session (GcrImporter *self, GckSession *session, GError *error)
321
 
{
322
 
        if (!session) {
323
 
                g_propagate_error (&self->pv->error, error);
324
 
                next_state (self, state_failure);
325
 
        } else {
326
 
                self->pv->session = session;
327
 
                next_state (self, state_create_object);
328
 
        }
329
 
}
330
 
 
331
 
static void
332
 
on_open_session (GObject *obj, GAsyncResult *res, gpointer user_data)
333
 
{
334
 
        GError *error = NULL;
335
 
        GckSession *session = gck_slot_open_session_finish (GCK_SLOT (obj), res, &error);
336
 
        complete_open_session (GCR_IMPORTER (user_data), session, error);
337
 
}
338
 
 
339
 
static void
340
 
state_open_session (GcrImporter *self, gboolean async)
341
 
{
342
 
        GckSession *session;
343
 
        GError *error = NULL;
344
 
        
345
 
        if (!self->pv->slot) {
346
 
                g_set_error (&self->pv->error, GCR_DATA_ERROR, GCR_ERROR_FAILURE, _("No location available to import to"));
347
 
                next_state (self, state_failure);
348
 
                
349
 
        } else {
350
 
                
351
 
                if (async) {
352
 
                        gck_slot_open_session_async (self->pv->slot, GCK_SESSION_READ_WRITE, self->pv->cancel,
353
 
                                                     on_open_session, self);
354
 
                } else {
355
 
                        session = gck_slot_open_session_full (self->pv->slot, GCK_SESSION_READ_WRITE, 0, NULL, NULL,
356
 
                                                              self->pv->cancel, &error);
357
 
                        complete_open_session (self, session, error);
358
 
                }
359
 
        }
360
 
}
361
 
 
362
 
/* ---------------------------------------------------------------------------------
363
 
 * INITIALIZE TOKEN
364
 
 * 
365
 
 * HACK: This is a big temporary hack to get, until the next version 
366
 
 * when we can fix this correctly.  
367
 
 */
368
 
 
369
 
static CK_RV
370
 
hacky_perform_initialize_pin (GckSlot *slot)
371
 
{
372
 
        CK_FUNCTION_LIST_PTR funcs;
373
 
        CK_SESSION_HANDLE session;
374
 
        CK_SLOT_ID slot_id;
375
 
        CK_RV rv;
376
 
        
377
 
        /* 
378
 
         * This hack only works when:
379
 
         *  
380
 
         *  - Module is protected authentication path
381
 
         *  - No other sessions are open.
382
 
         *  
383
 
         *  Thankfully this is the case with gnome-keyring-daemon and 
384
 
         *  the gnome-keyring tool. 
385
 
         */
386
 
        
387
 
        funcs = gck_module_get_functions (gck_slot_get_module (slot));
388
 
        g_return_val_if_fail (funcs, CKR_GENERAL_ERROR);
389
 
        slot_id = gck_slot_get_handle (slot);
390
 
        
391
 
        rv = funcs->C_OpenSession (slot_id, CKF_RW_SESSION | CKF_SERIAL_SESSION, NULL, NULL, &session);
392
 
        if (rv != CKR_OK)
393
 
                return rv;
394
 
        
395
 
        rv = funcs->C_Login (session, CKU_SO, NULL, 0);
396
 
        if (rv == CKR_OK) {
397
 
                rv = funcs->C_InitPIN (session, NULL, 0);
398
 
                funcs->C_Logout (session);
399
 
        }
400
 
        
401
 
        funcs->C_CloseSession (session);
402
 
        
403
 
        return rv;
404
 
}
405
 
 
406
 
static void
407
 
state_initialize_pin (GcrImporter *self, gboolean async)
408
 
{
409
 
        GckTokenInfo *info;
410
 
        gboolean initialize;
411
 
        CK_RV rv;
412
 
        
413
 
        g_assert (GCR_IS_IMPORTER (self));
414
 
        
415
 
        /* HACK: Doesn't function when async */
416
 
        if (!async) {
417
 
                g_return_if_fail (self->pv->slot);
418
 
                info = gck_slot_get_token_info (self->pv->slot);
419
 
                g_return_if_fail (info);
420
 
        
421
 
                initialize = !(info->flags & CKF_USER_PIN_INITIALIZED);
422
 
                gck_token_info_free (info);
423
 
 
424
 
                if (initialize) {
425
 
                        rv = hacky_perform_initialize_pin (self->pv->slot);
426
 
                        if (rv != CKR_OK) {
427
 
                                g_propagate_error (&self->pv->error, g_error_new (GCK_ERROR, rv, "%s", gck_message_from_rv (rv)));
428
 
                                next_state (self, state_failure);
429
 
                                return;
430
 
                        } 
431
 
                }
432
 
        }
433
 
 
434
 
        next_state (self, state_open_session);
435
 
}
436
 
 
437
 
/* ---------------------------------------------------------------------------------
438
 
 * IMPORT PROMPT
439
 
 */
440
 
 
441
 
static void
442
 
complete_import_prompt (GcrImporter *self, GcrImportDialog *dialog, gint response)
443
 
{
444
 
        GckSlot *slot;
445
 
 
446
 
        gtk_widget_hide (GTK_WIDGET (dialog));
447
 
        self->pv->prompted = TRUE;
448
 
 
449
 
        /* No dialog or dialog completed */
450
 
        if (response == GTK_RESPONSE_OK) {
451
 
 
452
 
                slot = _gcr_import_dialog_get_selected_slot (dialog);
453
 
                gcr_importer_set_slot (self, slot);
454
 
                next_state (self, state_initialize_pin);
455
 
                
456
 
        /* The dialog was cancelled or closed */
457
 
        } else {
458
 
                next_state (self, state_cancelled);
459
 
        }
460
 
}
461
 
 
462
 
static void
463
 
on_prompt_response (GtkDialog *dialog, gint response, gpointer user_data)
464
 
{
465
 
        complete_import_prompt (GCR_IMPORTER (user_data), GCR_IMPORT_DIALOG (dialog), response);
466
 
        g_object_unref (dialog);
467
 
}
468
 
 
469
 
static void 
470
 
state_import_prompt (GcrImporter *self, gboolean async)
471
 
{
472
 
        GcrImportDialog *dialog;
473
 
        gboolean prompt;
474
 
        gint response;
475
 
        
476
 
        g_assert (GCR_IS_IMPORTER (self));
477
 
        
478
 
        /* No need to prompt */
479
 
        if (self->pv->prompted == TRUE)
480
 
                prompt = FALSE;
481
 
        else if (self->pv->behavior == GCR_IMPORTER_PROMPT_ALWAYS)
482
 
                prompt = TRUE;
483
 
        else if (self->pv->behavior == GCR_IMPORTER_PROMPT_NEVER)
484
 
                prompt = FALSE;
485
 
        else 
486
 
                prompt = self->pv->slot ? FALSE : TRUE;
487
 
        
488
 
        if (prompt == FALSE) {
489
 
                next_state (self, state_initialize_pin);
490
 
                
491
 
        } else {
492
 
                
493
 
                dialog = _gcr_import_dialog_new ();
494
 
 
495
 
                _gcr_import_dialog_set_primary_text (dialog, _("Import Certificates/Keys"));
496
 
                _gcr_import_dialog_hide_password (dialog);
497
 
                
498
 
                if (self->pv->slot) {
499
 
                        _gcr_import_dialog_set_selected_slot (dialog, self->pv->slot);
500
 
                        _gcr_import_dialog_hide_selected_slot (dialog);
501
 
                } else {
502
 
                        _gcr_import_dialog_set_secondary_text (dialog, _("Choose a location to store the imported certificates/keys."));
503
 
                }
504
 
                        
505
 
                /* Prompt without blocking main loop */
506
 
                if (async) {
507
 
                        g_signal_connect (dialog, "response", G_CALLBACK (on_prompt_response), self);
508
 
                        gtk_widget_show (GTK_WIDGET (dialog));
509
 
                        
510
 
                /* Block mainloop */
511
 
                } else {
512
 
                        response = gtk_dialog_run (GTK_DIALOG (dialog));
513
 
                        complete_import_prompt (self, dialog, response);
514
 
                        g_object_unref (dialog);
515
 
                }
516
 
        }
517
 
}
518
 
 
519
 
/* -----------------------------------------------------------------------------
520
 
 * OBJECT 
521
 
 */
522
 
 
523
 
static GObject* 
524
 
gcr_importer_constructor (GType type, guint n_props, GObjectConstructParam *props) 
525
 
{
526
 
        GcrImporter *self = GCR_IMPORTER (G_OBJECT_CLASS (gcr_importer_parent_class)->constructor(type, n_props, props));
527
 
        g_return_val_if_fail (self, NULL);      
528
 
        
529
 
        return G_OBJECT (self);
530
 
}
531
 
 
532
 
static void
533
 
gcr_importer_init (GcrImporter *self)
534
 
{
535
 
        self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCR_TYPE_IMPORTER, GcrImporterPrivate);
536
 
        self->pv->behavior = GCR_IMPORTER_PROMPT_NEEDED;
537
 
        g_queue_init (&self->pv->queue);
538
 
}
539
 
 
540
 
static void
541
 
gcr_importer_dispose (GObject *obj)
542
 
{
543
 
        GcrImporter *self = GCR_IMPORTER (obj);
544
 
        
545
 
        cleanup_state_data (self);
546
 
        cleanup_import_data (self);
547
 
        
548
 
        if (self->pv->parser)
549
 
                g_object_unref (self->pv->parser);
550
 
        self->pv->parser = NULL;
551
 
        
552
 
        if (self->pv->slot)
553
 
                g_object_unref (self->pv->slot);
554
 
        self->pv->slot = NULL;
555
 
 
556
 
        G_OBJECT_CLASS (gcr_importer_parent_class)->dispose (obj);
557
 
}
558
 
 
559
 
static void
560
 
gcr_importer_finalize (GObject *obj)
561
 
{
562
 
        GcrImporter *self = GCR_IMPORTER (obj);
563
 
        
564
 
        g_assert (!self->pv->parser);
565
 
        g_assert (!self->pv->slot);
566
 
        
567
 
        G_OBJECT_CLASS (gcr_importer_parent_class)->finalize (obj);
568
 
}
569
 
 
570
 
static void
571
 
gcr_importer_set_property (GObject *obj, guint prop_id, const GValue *value, 
572
 
                           GParamSpec *pspec)
573
 
{
574
 
        GcrImporter *self = GCR_IMPORTER (obj);
575
 
        
576
 
        switch (prop_id) {
577
 
        case PROP_SLOT:
578
 
                gcr_importer_set_slot (self, g_value_get_object (value));
579
 
                break;
580
 
        case PROP_PROMPT_BEHAVIOR:
581
 
                gcr_importer_set_prompt_behavior (self, (GcrImporterPromptBehavior)g_value_get_int (value));
582
 
                break;
583
 
        default:
584
 
                G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
585
 
                break;
586
 
        }
587
 
}
588
 
 
589
 
static void
590
 
gcr_importer_get_property (GObject *obj, guint prop_id, GValue *value, 
591
 
                           GParamSpec *pspec)
592
 
{
593
 
        GcrImporter *self = GCR_IMPORTER (obj);
594
 
        
595
 
        switch (prop_id) {
596
 
        case PROP_SLOT:
597
 
                g_value_set_object (value, gcr_importer_get_slot (self));
598
 
                break;
599
 
        case PROP_PROMPT_BEHAVIOR:
600
 
                g_value_set_int (value, gcr_importer_get_prompt_behavior (self));
601
 
                break;
602
 
        default:
603
 
                G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
604
 
                break;
605
 
        }
606
 
}
607
 
 
608
 
static void
609
 
gcr_importer_class_init (GcrImporterClass *klass)
610
 
{
611
 
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
612
 
    
613
 
        gobject_class->constructor = gcr_importer_constructor;
614
 
        gobject_class->dispose = gcr_importer_dispose;
615
 
        gobject_class->finalize = gcr_importer_finalize;
616
 
        gobject_class->set_property = gcr_importer_set_property;
617
 
        gobject_class->get_property = gcr_importer_get_property;
618
 
    
619
 
        g_type_class_add_private (gobject_class, sizeof (GcrImporterPrivate));
620
 
 
621
 
        g_object_class_install_property (gobject_class, PROP_SLOT,
622
 
                   g_param_spec_object ("slot", "Slot", "PKCS#11 slot to import data into",
623
 
                                        GCK_TYPE_SLOT, G_PARAM_READWRITE));
624
 
 
625
 
        g_object_class_install_property (gobject_class, PROP_PROMPT_BEHAVIOR,
626
 
                   g_param_spec_int ("prompt-behavior", "Prompt Behavior", "Import Prompt Behavior",
627
 
                                     0, G_MAXINT, GCR_IMPORTER_PROMPT_NEEDED, G_PARAM_READWRITE));
628
 
 
629
 
        signals[QUEUED] = g_signal_new ("queued", GCR_TYPE_IMPORTER,
630
 
                                        G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GcrImporterClass, queued),
631
 
                                        NULL, NULL, _gcr_marshal_VOID__STRING_BOXED,
632
 
                                        G_TYPE_NONE, 1, G_TYPE_STRING, GCK_TYPE_ATTRIBUTES);
633
 
 
634
 
        signals[IMPORTED] = g_signal_new ("imported", GCR_TYPE_IMPORTER, 
635
 
                                        G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GcrImporterClass, imported),
636
 
                                        NULL, NULL, g_cclosure_marshal_VOID__OBJECT, 
637
 
                                        G_TYPE_NONE, 1, GCK_TYPE_OBJECT);
638
 
 
639
 
        _gcr_initialize ();
640
 
}
641
 
 
642
 
static gpointer
643
 
gcr_importer_real_get_user_data (GAsyncResult *base)
644
 
{
645
 
        g_return_val_if_fail (GCR_IS_IMPORTER (base), NULL);
646
 
        return GCR_IMPORTER (base)->pv->user_data;
647
 
}
648
 
 
649
 
static GObject* 
650
 
gcr_importer_real_get_source_object (GAsyncResult *base)
651
 
{
652
 
        g_return_val_if_fail (GCR_IS_IMPORTER (base), NULL);
653
 
        return G_OBJECT (base);
654
 
}
655
 
 
656
 
static void 
657
 
gcr_importer_async_result (GAsyncResultIface *iface)
658
 
{
659
 
        iface->get_source_object = gcr_importer_real_get_source_object;
660
 
        iface->get_user_data = gcr_importer_real_get_user_data;
661
 
}
662
 
 
663
 
/* -----------------------------------------------------------------------------
664
 
 * PUBLIC 
665
 
 */
666
 
 
667
 
GcrImporter*
668
 
gcr_importer_new (void)
669
 
{
670
 
        return g_object_new (GCR_TYPE_IMPORTER, NULL);
671
 
}
672
 
 
673
 
GckSlot*
674
 
gcr_importer_get_slot (GcrImporter *self)
675
 
{
676
 
        g_return_val_if_fail (GCR_IS_IMPORTER (self), NULL);
677
 
        return self->pv->slot;
678
 
}
679
 
 
680
 
void 
681
 
gcr_importer_set_slot (GcrImporter *self, GckSlot *slot)
682
 
{
683
 
        g_return_if_fail (GCR_IS_IMPORTER (self));
684
 
        
685
 
        if (slot)
686
 
                g_object_ref (slot);
687
 
        if (self->pv->slot)
688
 
                g_object_unref (self->pv->slot);
689
 
        self->pv->slot = slot;
690
 
        g_object_notify (G_OBJECT (self), "slot");
691
 
}
692
 
 
693
 
GcrImporterPromptBehavior
694
 
gcr_importer_get_prompt_behavior (GcrImporter *self)
695
 
{
696
 
        g_return_val_if_fail (GCR_IS_IMPORTER (self), GCR_IMPORTER_PROMPT_NEEDED);
697
 
        return self->pv->behavior;
698
 
}
699
 
 
700
 
void
701
 
gcr_importer_set_prompt_behavior (GcrImporter *self, GcrImporterPromptBehavior behavior)
702
 
{
703
 
        g_return_if_fail (GCR_IMPORTER (self));
704
 
        self->pv->behavior = behavior;
705
 
        g_object_notify (G_OBJECT (self), "prompt-behavior");
706
 
}
707
 
 
708
 
gboolean
709
 
gcr_importer_import (GcrImporter *self, GCancellable *cancel, GError **error)
710
 
{
711
 
        g_return_val_if_fail (GCR_IS_IMPORTER (self), FALSE);
712
 
        g_return_val_if_fail (!error || !*error, FALSE);
713
 
        g_return_val_if_fail (!self->pv->processing, FALSE);
714
 
 
715
 
        cleanup_import_data (self);
716
 
 
717
 
        if (cancel)
718
 
                self->pv->cancel = g_object_ref (cancel);
719
 
        self->pv->processing = TRUE;
720
 
        self->pv->async = FALSE;
721
 
 
722
 
        next_state (self, state_import_prompt);
723
 
 
724
 
        g_assert (!self->pv->processing);
725
 
        g_assert (!self->pv->cancel);
726
 
        
727
 
        if (!self->pv->succeeded) {
728
 
                g_propagate_error (error, self->pv->error);
729
 
                self->pv->error = NULL;
730
 
                return FALSE;
731
 
        }
732
 
        
733
 
        return TRUE;
734
 
}
735
 
 
736
 
void
737
 
gcr_importer_import_async (GcrImporter *self, GCancellable *cancel,
738
 
                           GAsyncReadyCallback callback, gpointer user_data)
739
 
{
740
 
        g_return_if_fail (GCR_IS_IMPORTER (self));
741
 
        g_return_if_fail (!self->pv->processing);
742
 
 
743
 
        cleanup_import_data (self);
744
 
 
745
 
        if (cancel)
746
 
                self->pv->cancel = g_object_ref (cancel);
747
 
        self->pv->processing = TRUE;
748
 
        self->pv->async = TRUE;
749
 
        self->pv->callback = callback;
750
 
        self->pv->user_data = user_data;
751
 
 
752
 
        next_state (self, state_import_prompt);
753
 
        g_assert (self->pv->processing);
754
 
}
755
 
 
756
 
gboolean
757
 
gcr_importer_import_finish (GcrImporter *self, GAsyncResult *res, GError **error)
758
 
{
759
 
        g_return_val_if_fail (GCR_IS_IMPORTER (self), FALSE);
760
 
        g_return_val_if_fail (GCR_IMPORTER (res) == self, FALSE);
761
 
        g_return_val_if_fail (!error || !*error, FALSE);
762
 
        g_return_val_if_fail (!self->pv->processing, FALSE);
763
 
 
764
 
        g_assert (!self->pv->cancel);
765
 
 
766
 
        if (!self->pv->succeeded) {
767
 
                g_propagate_error (error, self->pv->error);
768
 
                self->pv->error = NULL;
769
 
                return FALSE;
770
 
        }
771
 
        
772
 
        return TRUE;
773
 
}
774
 
 
775
 
 
776
 
void
777
 
gcr_importer_listen (GcrImporter *self, GcrParser *parser)
778
 
{
779
 
        g_return_if_fail (GCR_IS_IMPORTER (self));
780
 
        g_return_if_fail (GCR_IS_PARSER (self));
781
 
 
782
 
        /* Listen in to the parser */
783
 
        g_signal_connect_object (parser, "parsed", G_CALLBACK (on_parser_parsed), self, 0);
784
 
        g_signal_connect_object (parser, "authenticate", G_CALLBACK (on_parser_authenticate), self, 0);
785
 
}
786
 
 
787
 
void
788
 
gcr_importer_queue (GcrImporter *self, const gchar *label, GckAttributes *attrs)
789
 
{
790
 
        g_return_if_fail (GCR_IS_IMPORTER (self));
791
 
        g_return_if_fail (attrs);
792
 
 
793
 
        g_queue_push_tail (&self->pv->queue, gck_attributes_ref (attrs));
794
 
        g_signal_emit (self, signals[QUEUED], 0, label, attrs);
795
 
}
796
 
 
797
 
#ifndef GCR_DISABLE_DEPRECATED
798
 
 
799
 
GcrParser*
800
 
gcr_importer_get_parser (GcrImporter *self)
801
 
{
802
 
        g_warning ("gcr_importer_get_parser() is no longer supported "
803
 
                   "Use gcr_importer_listen() instead.");
804
 
        return NULL;
805
 
}
806
 
 
807
 
void
808
 
gcr_importer_set_parser (GcrImporter *self, GcrParser *parser)
809
 
{
810
 
        g_warning ("gcr_importer_set_parser() is no longer supported "
811
 
                   "Use gcr_importer_listen() instead.");
812
 
}
813
 
 
814
 
#endif /* GCR_DISABLE_DEPRECATED */