~ubuntu-branches/ubuntu/trusty/gq/trusty

« back to all changes in this revision

Viewing changes to src/gq-export-dialog.c

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese
  • Date: 2009-10-25 23:34:56 UTC
  • mfrom: (1.1.4 upstream) (3.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20091025233456-i794n3yg2cff930j
Tags: 1.3.4-1
* QA upload.
  + Set maintainer to Debian QA Group <packages@qa.debian.org>.
* New upstream release. (Closes: #534705).
  + Does not segfault on amd64. (Closes: #444312).
  + Remove all existing patches and change patch system to quilt.
  + Replace dpatch build-dep with quilt.
* 01_desktop_file.diff - Remove encoding and bogus categories 
  from desktop file.
* Copy in config.{sub,guess} on configure, rm them on clean.
  + Add build-dep on autotools-dev.
* Make clean not ignore errors.
* Add copyright holders and version path to GPL (GPL-2).
* Update watch file to use SF redirector. (Closes: #449749).
* Bump debhelper build-dep and compat to 5.
* Bump Standards Version to 3.8.3.
  + Menu policy transition.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of GQ
 
2
 *
 
3
 * AUTHORS
 
4
 *     Sven Herzberg
 
5
 *
 
6
 * Copyright (C) 1998-2003 Bert Vermeulen
 
7
 * Copyright (C) 2002-2003 Peter Stamfest
 
8
 * Copyright (C) 2006  Sven Herzberg
 
9
 *
 
10
 * This program is released under the Gnu General Public License with
 
11
 * the additional exemption that compiling, linking, and/or using
 
12
 * OpenSSL is allowed.
 
13
 *
 
14
 * This program is free software; you can redistribute it and/or
 
15
 * modify it under the terms of the GNU General Public License as
 
16
 * published by the Free Software Foundation; either version 2 of the
 
17
 * License, or (at your option) any later version.
 
18
 *
 
19
 * This program is distributed in the hope that it will be useful,
 
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
 * GNU General Public License for more details.
 
23
 *
 
24
 * You should have received a copy of the GNU General Public License
 
25
 * along with this program; if not, write to the Free Software
 
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
27
 * USA
 
28
 */
 
29
 
 
30
#include "gq-export-dialog.h"
 
31
 
 
32
#include <glib.h>
 
33
#include <glib/gi18n.h>
 
34
#include <gtk/gtk.h>
 
35
#include <string.h>
 
36
#include <errno.h>              /* errno */
 
37
#include <stdio.h>              /* FILE */
 
38
#include <stdlib.h>             /* free - MUST get rid of malloc/free */
 
39
 
 
40
#ifdef HAVE_CONFIG_H
 
41
# include  <config.h>
 
42
#endif /* HAVE_CONFIG_H */
 
43
 
 
44
#include "browse-dnd.h"         /* copy_entry et al */
 
45
#include "common.h"
 
46
#include "configfile.h"         /* config */
 
47
#include "errorchain.h"
 
48
#include "encode.h"
 
49
#include "gq-browser-node-dn.h"
 
50
#include "gq-browser-node-reference.h"
 
51
#include "gq-utilities.h"
 
52
#include "ldif.h"
 
53
#include "search.h"             /* fill_out_search */
 
54
#include "template.h"           /* struct gq_template */
 
55
 
 
56
typedef struct {
 
57
        GtkFileChooserDialog base_instance;
 
58
        GList    * to_export;
 
59
        GtkWidget* filetype_box;
 
60
        GtkWidget* filetype_label;
 
61
        GtkWidget* filetype_combo;
 
62
} GqExport;
 
63
typedef GtkFileChooserDialogClass GqExportClass;
 
64
 
 
65
/* GType */
 
66
GType gq_export_get_type(void);
 
67
#define GQ_TYPE_EXPORT         (gq_export_get_type())
 
68
#define GQ_EXPORT(i)           (G_TYPE_CHECK_INSTANCE_CAST((i), GQ_TYPE_EXPORT, GqExport))
 
69
G_DEFINE_TYPE(GqExport, gq_export, GTK_TYPE_FILE_CHOOSER_DIALOG);
 
70
 
 
71
static gchar const* type_names[] = {
 
72
        N_("ldifformat|UMich/OpenLDAP style (no comments/version)"),
 
73
        N_("ldifformat|LDIF Version 1 (RFC2849)")
 
74
};
 
75
 
 
76
static void
 
77
gq_export_init(GqExport* self)
 
78
{
 
79
        GtkListStore* store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
 
80
        GqLdifType type;
 
81
        // TRANSLATORS: there is a unicode symbol for the ellipsis (...)
 
82
        gtk_window_set_title(GTK_WINDOW(self), _("Export Entries..."));
 
83
        gtk_dialog_add_buttons(GTK_DIALOG(self),
 
84
                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
85
                               GTK_STOCK_SAVE,   GTK_RESPONSE_ACCEPT,
 
86
                               NULL);
 
87
 
 
88
#warning "FIXME: add filter on text/x-ldif and *.ldif"
 
89
 
 
90
        self->filetype_box   = gtk_hbox_new(FALSE, 6);
 
91
        self->filetype_label = gtk_label_new(_("LDIF Format:"));
 
92
#warning "FIXME: set mnemonic and target widget"
 
93
        gtk_box_pack_start(GTK_BOX(self->filetype_box), self->filetype_label,
 
94
                           FALSE, FALSE, 0);
 
95
        self->filetype_combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
 
96
        gtk_box_pack_start_defaults(GTK_BOX(self->filetype_box), self->filetype_combo);
 
97
        g_object_unref(store);
 
98
 
 
99
        {
 
100
                GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
 
101
                GtkCellLayout* layout = GTK_CELL_LAYOUT(self->filetype_combo);
 
102
 
 
103
                gtk_cell_layout_pack_start(layout, renderer, TRUE);
 
104
                gtk_cell_layout_set_attributes(layout, renderer,
 
105
                                               "text", 1,
 
106
                                               NULL);
 
107
        }
 
108
 
 
109
        for(type = 0; type < G_N_ELEMENTS(type_names); type++) {
 
110
                GtkTreeIter iter;
 
111
                gtk_list_store_append(store, &iter);
 
112
                gtk_list_store_set(store, &iter,
 
113
                                   0, type,
 
114
                                   1, Q_(type_names[type]),
 
115
                                   -1);
 
116
 
 
117
                if(type == DEFAULT_LDIFFORMAT) {
 
118
                        gtk_combo_box_set_active_iter(GTK_COMBO_BOX(self->filetype_combo), &iter);
 
119
                }
 
120
        }
 
121
#warning "FIXME: add help button to explain the different formats"
 
122
}
 
123
 
 
124
static GObject*
 
125
export_constructor(GType                  type,
 
126
                   guint                  n_props,
 
127
                   GObjectConstructParam* props)
 
128
{
 
129
        GObject* object = G_OBJECT_CLASS(gq_export_parent_class)->constructor(type, n_props, props);
 
130
        gtk_file_chooser_set_action(GTK_FILE_CHOOSER(object),
 
131
                                    GTK_FILE_CHOOSER_ACTION_SAVE);
 
132
        gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(object),
 
133
                                          GQ_EXPORT(object)->filetype_box);
 
134
        gtk_widget_show_all(GQ_EXPORT(object)->filetype_box);
 
135
        return object;
 
136
}
 
137
 
 
138
static void
 
139
export_finalize(GObject* object)
 
140
{
 
141
        g_list_foreach(GQ_EXPORT(object)->to_export, (GFunc)g_object_unref, NULL);
 
142
        g_list_free(GQ_EXPORT(object)->to_export);
 
143
        GQ_EXPORT(object)->to_export = NULL;
 
144
 
 
145
        G_OBJECT_CLASS(gq_export_parent_class)->finalize(object);
 
146
}
 
147
 
 
148
static void
 
149
gq_export_class_init(GqExportClass* self_class)
 
150
{
 
151
        GObjectClass* object_class = G_OBJECT_CLASS(self_class);
 
152
 
 
153
        object_class->constructor = export_constructor;
 
154
        object_class->finalize    = export_finalize;
 
155
}
 
156
 
 
157
static void
 
158
dump_subtree_ok_callback(GqExport* ex)
 
159
{
 
160
        GtkTreeIter iter;
 
161
        GqLdifType  type;
 
162
     LDAPMessage *res = NULL, *e;
 
163
     LDAP *ld = NULL;
 
164
     GList *I;
 
165
     int num_entries;
 
166
     const char *filename;
 
167
     FILE *outfile = NULL;
 
168
     GString *out = NULL;
 
169
     GString *gmessage = NULL;
 
170
     size_t written;
 
171
     int ctx;
 
172
     GqServer *last = NULL;
 
173
 
 
174
     out = g_string_sized_new(2048);
 
175
 
 
176
     ctx = error_new_context(_("Dump subtree"), GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(ex))));
 
177
 
 
178
     if(g_list_length(ex->to_export) == 0) {
 
179
          error_push(ctx, _("Nothing to dump!"));
 
180
#warning "FIXME: isn't this some kind of late?"
 
181
          goto fail;
 
182
     }
 
183
 
 
184
     set_busycursor();
 
185
 
 
186
        /* obtain filename and open file for reading */
 
187
        filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ex));
 
188
 
 
189
        gtk_combo_box_get_active_iter(GTK_COMBO_BOX(GQ_EXPORT(ex)->filetype_combo),
 
190
                                      &iter);
 
191
        gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(GQ_EXPORT(ex)->filetype_combo)),
 
192
                           &iter,
 
193
                           0, &type,
 
194
                           -1);
 
195
 
 
196
     if( (outfile = fopen(filename, "w")) == NULL) {
 
197
          error_push(ctx, _("Could not open output file '%1$s': %2$s"),
 
198
                     filename, strerror(errno));
 
199
 
 
200
          goto fail;
 
201
     } else {
 
202
          /* AFAIK, the UMich LDIF format doesn't take comments or a
 
203
             version string */
 
204
          if (type != LDIF_UMICH) {
 
205
               g_string_truncate(out, 0);
 
206
 
 
207
               prepend_ldif_header(out, ex->to_export);
 
208
 
 
209
               written = fwrite(out->str, 1, out->len, outfile);
 
210
               if(written != (size_t) out->len) {
 
211
                    error_push(ctx,
 
212
                               _("Save to '%3$s' failed: Only %1$d of %2$d bytes written"),
 
213
                               written, out->len, filename);
 
214
                    goto fail; /* sometimes goto is useful */
 
215
               }
 
216
          }
 
217
 
 
218
          num_entries = 0;
 
219
          gmessage = g_string_sized_new(256);
 
220
          for (I = g_list_first(ex->to_export) ; I ; I = g_list_next(I)) {
 
221
               GqServerDn *dos = I->data;
 
222
 
 
223
               LDAPControl ct;
 
224
               LDAPControl *ctrls[2] = { NULL, NULL } ;
 
225
               char *attrs[] = {
 
226
                    LDAP_ALL_USER_ATTRIBUTES,
 
227
                    "ref",
 
228
                    NULL
 
229
               };
 
230
               int rc;
 
231
 
 
232
               ct.ldctl_oid             = LDAP_CONTROL_MANAGEDSAIT;
 
233
               ct.ldctl_value.bv_val    = NULL;
 
234
               ct.ldctl_value.bv_len    = 0;
 
235
               ct.ldctl_iscritical      = 1;
 
236
 
 
237
               ctrls[0] = &ct;
 
238
 
 
239
               statusbar_msg(_("Search on %s"), gq_server_dn_get_dn(dos));
 
240
 
 
241
               if (last != gq_server_dn_get_server(dos)) {
 
242
                    if (last) {
 
243
                         close_connection(last, FALSE);
 
244
                         last = NULL;
 
245
                    }
 
246
 
 
247
                    if( (ld = open_connection(ctx, gq_server_dn_get_server(dos))) == NULL) {
 
248
                         /* no extra error, open_connection does error
 
249
                            reporting itself... */
 
250
                         goto fail;
 
251
                    }
 
252
 
 
253
                    last = gq_server_dn_get_server(dos);
 
254
               }
 
255
 
 
256
               rc = ldap_search_ext_s(ld, gq_server_dn_get_dn(dos),
 
257
                                      dos->flags == LDAP_SCOPE_SUBTREE ? LDAP_SCOPE_SUBTREE : LDAP_SCOPE_BASE,
 
258
                                      "(objectClass=*)",
 
259
                                      attrs,
 
260
                                      0,
 
261
                                      ctrls,            /* serverctrls */
 
262
                                      NULL,             /* clientctrls */
 
263
                                      NULL,             /* timeout */
 
264
                                      LDAP_NO_LIMIT,    /* sizelimit */
 
265
                                      &res);
 
266
 
 
267
               if(rc == LDAP_NOT_SUPPORTED) {
 
268
                    rc = ldap_search_s(ld, gq_server_dn_get_dn(dos),
 
269
                                       dos->flags == LDAP_SCOPE_SUBTREE ? LDAP_SCOPE_SUBTREE : LDAP_SCOPE_BASE,
 
270
                                       "(objectClass=*)",
 
271
                                       attrs, 0, &res);
 
272
               }
 
273
 
 
274
               if (rc == LDAP_SUCCESS) {
 
275
                    for(e = ldap_first_entry(ld, res); e; e = ldap_next_entry(ld, e)) {
 
276
                         g_string_truncate(out, 0);
 
277
                         ldif_entry_out(out, ld, e, ctx);
 
278
                         num_entries++;
 
279
 
 
280
                         written = fwrite(out->str, 1, out->len, outfile);
 
281
                         if(written != (size_t) out->len) {
 
282
                              g_string_sprintf(gmessage,
 
283
                                               _("%1$d of %2$d bytes written"),
 
284
                                               written, out->len);
 
285
                              error_popup(_("Save failed"), gmessage->str,
 
286
                                          GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(ex))));
 
287
 
 
288
                              ldap_msgfree(res);
 
289
                              goto fail;
 
290
                         }
 
291
 
 
292
                    }
 
293
                    ldap_msgfree(res);
 
294
               } else if (rc == LDAP_SERVER_DOWN) {
 
295
                    gq_server_dn_get_server(dos)->server_down++;
 
296
 
 
297
                    error_push(ctx,
 
298
                               _("Server '%s' down. Export may be incomplete!"),
 
299
                               gq_server_get_name(gq_server_dn_get_server(dos)));
 
300
                    push_ldap_addl_error(ld, ctx);
 
301
                    goto fail;
 
302
               } else {
 
303
                    /* report error */
 
304
                    error_push(ctx,
 
305
                               _("LDAP error while searching below '%s'."
 
306
                                 " Export may be incomplete!"),
 
307
                               gq_server_dn_get_dn(dos));
 
308
                    push_ldap_addl_error(ld, ctx);
 
309
                    goto fail;
 
310
               }
 
311
          }
 
312
 
 
313
          statusbar_msg(ngettext("%1$d entry exported to %2$s",
 
314
                                 "%1$d entries exported to %2$s", num_entries),
 
315
                        num_entries, filename);
 
316
 
 
317
#warning "FIXME: store the last used type in the config file"
 
318
#warning "FIXME: store the last used location in the config file"
 
319
     }
 
320
 
 
321
 fail:          /* labels are only good for cleaning up, really */
 
322
     if (outfile) fclose(outfile);
 
323
 
 
324
     set_normalcursor();
 
325
     if (out) g_string_free(out, TRUE);
 
326
     if (gmessage) g_string_free(gmessage, TRUE);
 
327
     if (ld && last) close_connection(last, FALSE);
 
328
 
 
329
     error_flush(ctx);
 
330
}
 
331
 
 
332
void
 
333
gq_export_server_dns(int        error_context G_GNUC_UNUSED,
 
334
                     GtkWindow* parent,
 
335
                     GList    * to_export)
 
336
{
 
337
#warning "FIXME: provide a good default file name"
 
338
        GqExport* ex = g_object_new(GQ_TYPE_EXPORT, NULL);
 
339
        gboolean finished = FALSE;
 
340
        gtk_window_set_transient_for(GTK_WINDOW(ex), parent);
 
341
 
 
342
        ex->to_export = to_export;
 
343
 
 
344
        g_signal_connect_swapped(ex, "key-press-event",
 
345
                                 G_CALLBACK(close_on_esc), ex);
 
346
 
 
347
        do {
 
348
                switch(gtk_dialog_run(GTK_DIALOG(ex))) {
 
349
                case GTK_RESPONSE_CANCEL:
 
350
                case GTK_RESPONSE_DELETE_EVENT:
 
351
                        finished = TRUE;
 
352
                        break;
 
353
                case GTK_RESPONSE_ACCEPT:
 
354
                        dump_subtree_ok_callback(ex);
 
355
                        finished = TRUE;
 
356
                        break;
 
357
                default:
 
358
                        g_assert_not_reached();
 
359
                }
 
360
        } while(!finished);
 
361
 
 
362
        gtk_widget_destroy(GTK_WIDGET(ex));
 
363
}
 
364