1
/* This file is part of GQ
6
* Copyright (C) 1998-2003 Bert Vermeulen
7
* Copyright (C) 2002-2003 Peter Stamfest
8
* Copyright (C) 2006 Sven Herzberg
10
* This program is released under the Gnu General Public License with
11
* the additional exemption that compiling, linking, and/or using
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.
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.
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
30
#include "gq-export-dialog.h"
33
#include <glib/gi18n.h>
36
#include <errno.h> /* errno */
37
#include <stdio.h> /* FILE */
38
#include <stdlib.h> /* free - MUST get rid of malloc/free */
42
#endif /* HAVE_CONFIG_H */
44
#include "browse-dnd.h" /* copy_entry et al */
46
#include "configfile.h" /* config */
47
#include "errorchain.h"
49
#include "gq-browser-node-dn.h"
50
#include "gq-browser-node-reference.h"
51
#include "gq-utilities.h"
53
#include "search.h" /* fill_out_search */
54
#include "template.h" /* struct gq_template */
57
GtkFileChooserDialog base_instance;
59
GtkWidget* filetype_box;
60
GtkWidget* filetype_label;
61
GtkWidget* filetype_combo;
63
typedef GtkFileChooserDialogClass GqExportClass;
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);
71
static gchar const* type_names[] = {
72
N_("ldifformat|UMich/OpenLDAP style (no comments/version)"),
73
N_("ldifformat|LDIF Version 1 (RFC2849)")
77
gq_export_init(GqExport* self)
79
GtkListStore* store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
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,
88
#warning "FIXME: add filter on text/x-ldif and *.ldif"
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,
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);
100
GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
101
GtkCellLayout* layout = GTK_CELL_LAYOUT(self->filetype_combo);
103
gtk_cell_layout_pack_start(layout, renderer, TRUE);
104
gtk_cell_layout_set_attributes(layout, renderer,
109
for(type = 0; type < G_N_ELEMENTS(type_names); type++) {
111
gtk_list_store_append(store, &iter);
112
gtk_list_store_set(store, &iter,
114
1, Q_(type_names[type]),
117
if(type == DEFAULT_LDIFFORMAT) {
118
gtk_combo_box_set_active_iter(GTK_COMBO_BOX(self->filetype_combo), &iter);
121
#warning "FIXME: add help button to explain the different formats"
125
export_constructor(GType type,
127
GObjectConstructParam* props)
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);
139
export_finalize(GObject* object)
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;
145
G_OBJECT_CLASS(gq_export_parent_class)->finalize(object);
149
gq_export_class_init(GqExportClass* self_class)
151
GObjectClass* object_class = G_OBJECT_CLASS(self_class);
153
object_class->constructor = export_constructor;
154
object_class->finalize = export_finalize;
158
dump_subtree_ok_callback(GqExport* ex)
162
LDAPMessage *res = NULL, *e;
166
const char *filename;
167
FILE *outfile = NULL;
169
GString *gmessage = NULL;
172
GqServer *last = NULL;
174
out = g_string_sized_new(2048);
176
ctx = error_new_context(_("Dump subtree"), GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(ex))));
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?"
186
/* obtain filename and open file for reading */
187
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ex));
189
gtk_combo_box_get_active_iter(GTK_COMBO_BOX(GQ_EXPORT(ex)->filetype_combo),
191
gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(GQ_EXPORT(ex)->filetype_combo)),
196
if( (outfile = fopen(filename, "w")) == NULL) {
197
error_push(ctx, _("Could not open output file '%1$s': %2$s"),
198
filename, strerror(errno));
202
/* AFAIK, the UMich LDIF format doesn't take comments or a
204
if (type != LDIF_UMICH) {
205
g_string_truncate(out, 0);
207
prepend_ldif_header(out, ex->to_export);
209
written = fwrite(out->str, 1, out->len, outfile);
210
if(written != (size_t) out->len) {
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 */
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;
224
LDAPControl *ctrls[2] = { NULL, NULL } ;
226
LDAP_ALL_USER_ATTRIBUTES,
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;
239
statusbar_msg(_("Search on %s"), gq_server_dn_get_dn(dos));
241
if (last != gq_server_dn_get_server(dos)) {
243
close_connection(last, FALSE);
247
if( (ld = open_connection(ctx, gq_server_dn_get_server(dos))) == NULL) {
248
/* no extra error, open_connection does error
249
reporting itself... */
253
last = gq_server_dn_get_server(dos);
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,
261
ctrls, /* serverctrls */
262
NULL, /* clientctrls */
264
LDAP_NO_LIMIT, /* sizelimit */
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,
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);
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"),
285
error_popup(_("Save failed"), gmessage->str,
286
GTK_WIDGET(gtk_window_get_transient_for(GTK_WINDOW(ex))));
294
} else if (rc == LDAP_SERVER_DOWN) {
295
gq_server_dn_get_server(dos)->server_down++;
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);
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);
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);
317
#warning "FIXME: store the last used type in the config file"
318
#warning "FIXME: store the last used location in the config file"
321
fail: /* labels are only good for cleaning up, really */
322
if (outfile) fclose(outfile);
325
if (out) g_string_free(out, TRUE);
326
if (gmessage) g_string_free(gmessage, TRUE);
327
if (ld && last) close_connection(last, FALSE);
333
gq_export_server_dns(int error_context G_GNUC_UNUSED,
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);
342
ex->to_export = to_export;
344
g_signal_connect_swapped(ex, "key-press-event",
345
G_CALLBACK(close_on_esc), ex);
348
switch(gtk_dialog_run(GTK_DIALOG(ex))) {
349
case GTK_RESPONSE_CANCEL:
350
case GTK_RESPONSE_DELETE_EVENT:
353
case GTK_RESPONSE_ACCEPT:
354
dump_subtree_ok_callback(ex);
358
g_assert_not_reached();
362
gtk_widget_destroy(GTK_WIDGET(ex));