2
GQ -- a GTK-based LDAP client
3
Copyright (C) 1998-2003 Bert Vermeulen
4
Copyright (C) 2002-2003 Peter Stamfest
5
Copyright (C) 2006 Sven Herzberg
7
This program is released under the Gnu General Public License with
8
the additional exemption that compiling, linking, and/or using
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 2 of the License, or
14
(at your option) any later version.
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
21
You should have received a copy of the GNU General Public License
22
along with this program; if not, write to the Free Software
23
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
#include "gq-utilities.h"
29
#include <glib/gi18n.h>
31
#include <gdk/gdkkeysyms.h>
41
#endif /* HAVE_CONFIG_H */
44
#ifdef HAVE_LDAP_STR2OBJECTCLASS
45
# include <ldap_schema.h>
47
#ifdef LDAP_OPT_NETWORK_TIMEOUT
51
#include <glade/glade.h>
54
#include "configfile.h"
57
#include "errorchain.h"
58
#include "gq-input-form.h"
60
#include "gq-server-list.h"
61
#include "gq-window.h" /* message_log_append */
66
* clear cached server schema
68
void clear_server_schema(GqServer *server)
70
#ifdef HAVE_LDAP_STR2OBJECTCLASS
72
struct server_schema *ss;
81
ldap_objectclass_free(list->data);
91
ldap_attributetype_free(list->data);
101
ldap_matchingrule_free(list->data);
111
ldap_syntax_free(list->data);
117
FREE(server->ss, "struct server_schema");
121
server->flags &= ~SERVER_HAS_NO_SCHEMA;
131
delete_entry_recursive(int delete_context,
140
LDAPControl *ctrls[2] = { NULL, NULL } ;
141
LDAPMessage *res = NULL, *e;
143
c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
144
c.ldctl_value.bv_val = NULL;
145
c.ldctl_value.bv_len = 0;
146
c.ldctl_iscritical = 1;
150
/* FIXME confirm-mod check here */
154
if( (ld = open_connection(delete_context, server) ) == NULL) {
160
int something_to_do = 1;
161
static char* attrs [] = {"dn", NULL};
163
while (something_to_do) {
165
msg = ldap_search_ext_s(ld, dn,
168
(char **)attrs, /* attrs */
170
ctrls, /* serverctrls */
171
NULL, /* clientctrls */
173
LDAP_NO_LIMIT, /* sizelimit */
176
if(msg == LDAP_NOT_SUPPORTED) {
177
msg = ldap_search_s(ld, dn, LDAP_SCOPE_ONELEVEL,
179
(char **) attrs, 1, &res);
182
if(msg == LDAP_SUCCESS) {
183
for (e = ldap_first_entry(ld, res); e ;
184
e = ldap_next_entry(ld, e)) {
185
char *dn2 = ldap_get_dn(ld, e);
186
gboolean delok = delete_entry_full(delete_context,
188
if (dn2) ldap_memfree(dn2);
196
} else if (msg == LDAP_SERVER_DOWN) {
197
server->server_down++;
200
if (res) ldap_msgfree(res);
205
statusbar_msg(_("Deleting: %s"), dn);
207
msg = ldap_delete_ext_s(ld, dn, ctrls, NULL);
209
if(msg == LDAP_NOT_SUPPORTED) {
210
msg = ldap_delete_s(ld, dn);
213
#if HAVE_LDAP_CLIENT_CACHE
214
ldap_uncache_entry(ld, dn);
217
if(msg != LDAP_SUCCESS) {
218
error_push(delete_context,
219
"Error deleting DN '%1$s' on '%2$s': %3$s",
220
dn, gq_server_get_name(server), ldap_err2string(msg));
224
statusbar_msg(_("Deleted %s"), dn);
228
if (res) ldap_msgfree(res);
230
close_connection(server, FALSE);
237
delete_entry(int delete_context,
241
return delete_entry_recursive(delete_context, server, dn, FALSE);
245
delete_entry_full(int delete_context,
249
return delete_entry_recursive(delete_context, server, dn, TRUE);
253
* display hourglass cursor on mainwin
255
void set_busycursor(void)
257
GdkCursor *busycursor;
259
busycursor = gdk_cursor_new(GDK_WATCH);
260
gdk_window_set_cursor(mainwin.mainwin->window, busycursor);
261
gdk_cursor_destroy(busycursor);
267
* set mainwin cursor to default
269
void set_normalcursor(void)
272
gdk_window_set_cursor(mainwin.mainwin->window, NULL);
277
* callback for key_press_event on a widget, destroys obj if key was esc
279
int close_on_esc(GtkWidget *widget, GdkEventKey *event, gpointer obj)
281
if(event && event->type == GDK_KEY_PRESS && event->keyval == GDK_Escape) {
282
gtk_widget_destroy(GTK_WIDGET(obj));
283
g_signal_stop_emission_by_name(widget, "key_press_event");
292
* callback for key_press_event on a widget, calls func if key was esc
294
int func_on_esc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window)
296
void (*func)(GtkWidget *);
298
if(event && event->type == GDK_KEY_PRESS && event->keyval == GDK_Escape) {
299
func = gtk_object_get_data(GTK_OBJECT(window), "close_func");
301
g_signal_stop_emission_by_name(widget, "key_press_event");
309
int tokenize(const struct tokenlist *list, const char *keyword)
313
for(i = 0; list[i].keyword && strlen(list[i].keyword); i++)
314
if(!strcasecmp(list[i].keyword, keyword))
315
return(list[i].token);
321
const char *detokenize(const struct tokenlist *list, int token)
325
for(i = 0; list[i].keyword && strlen(list[i].keyword); i++)
326
if(list[i].token == token)
327
return(list[i].keyword);
329
return(list[0].keyword);
333
const void *detokenize_data(const struct tokenlist *list, int token)
337
for(i = 0; strlen(list[i].keyword); i++)
338
if(list[i].token == token)
339
return(list[i].data);
341
return(list[0].data);
345
* return pointer to username (must be freed)
347
char *get_username(void)
349
struct passwd *pwent;
353
pwent = getpwuid(getuid());
354
if(pwent && pwent->pw_name)
355
username = strdup(pwent->pw_name);
362
/* these should probably belong to GqWindow */
363
#warning "FIXME: move into GqWindow"
364
static guint context = 0, msgid = 0;
368
* display message in main window's statusbar, and flushes the
372
statusbar_msg(gchar const* fmt, ...)
374
/* do not use g_string_sprintf, as it usually does not support
375
numbered arguments */
376
int len = strlen(fmt) * 2;
387
n = g_vsnprintf(buf, len, fmt, ap);
390
if (n > len || n == -1) {
401
statusbar_msg_clear();
403
msgid = gtk_statusbar_push(GTK_STATUSBAR(mainwin.statusbar),
405
message_log_append(buf);
408
/* make sure statusbar gets updated right away */
409
gq_main_loop_flush();
412
void statusbar_msg_clear()
416
gtk_statusbar_get_context_id(GTK_STATUSBAR(mainwin.statusbar),
419
gtk_statusbar_remove(GTK_STATUSBAR(mainwin.statusbar),
424
* return pointer to GqServer matching the canonical name
426
GqServer *server_by_canon_name(const char *name,
427
gboolean include_transient)
429
GqServer *server = NULL;
432
if(name == NULL || name[0] == '\0')
435
server = gq_server_list_get_by_canon_name(gq_server_list_get(), name);
436
if(!server && include_transient) {
437
for (I = transient_servers ; I ; I = g_list_next(I)) {
438
if(!strcmp(((GqServer*)I->data)->canon_name, name)) {
448
is_transient_server(const GqServer *server) {
449
g_return_val_if_fail(GQ_IS_SERVER(server), FALSE);
450
return !gq_server_list_contains(gq_server_list_get(), server);
454
* check if entry has a subtree
456
int is_leaf_entry(int error_context,
457
GqServer *server, char *dn)
461
int msg, is_leaf, rc;
467
LDAPControl *ctrls[2] = { NULL, NULL } ;
470
c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
471
c.ldctl_value.bv_val = NULL;
472
c.ldctl_value.bv_len = 0;
473
c.ldctl_iscritical = 1;
481
if( (ld = open_connection(error_context, server) ) == NULL) {
486
statusbar_msg(_("Checking subtree for %s"), dn);
488
rc = ldap_search_ext(ld, dn, LDAP_SCOPE_ONELEVEL, "(objectclass=*)",
491
ctrls, /* serverctrls */
492
NULL, /* clientctrls */
494
LDAP_NO_LIMIT, /* sizelimit */
498
if( (ldap_result(ld, msg, 0, NULL, &res) != LDAP_RES_SEARCH_ENTRY))
501
ldap_abandon(ld, msg);
504
close_connection(server, FALSE);
506
statusbar_msg_clear();
512
* check if child is a direct subentry of possible_parent
514
gboolean is_direct_parent(char *child, char *possible_parent)
516
/* SHOULD use gq_ldap_explode_dn for this */
517
char *c = g_utf8_strchr(child, -1, ',');
518
if (c && (strcasecmp(c + 1, possible_parent) == 0)) return TRUE;
523
* check if child is a (possibly indirect) subentry of possible_ancestor
526
is_ancestor(gchar const* child,
527
gchar const* possible_ancestor)
529
char **rdn = gq_ldap_explode_dn(child, FALSE);
534
for (n = 0 ; rdn[n] ; n++) {
537
s = g_string_new("");
538
for (n-- ; n >= 0 ; n--) {
539
g_string_insert(s, 0, rdn[n]);
540
if ((strcasecmp(s->str, possible_ancestor) == 0)) {
544
g_string_insert(s, 0, ",");
547
g_string_free(s, TRUE);
548
gq_exploded_free(rdn);
553
GList *ar2glist(char *ar[])
559
/* gtk_combo_set_popdown_strings() can't handle an
560
empty list, so give it a list with an empty entry */
561
tmp = g_list_append(NULL, "");
568
tmp = g_list_append(tmp, ar[i++]);
575
* pops up a warning dialog (with hand icon), and displays all messages in
576
* the GList , one per line. The GList is freed here.
578
void warning_popup(GList *messages)
581
GtkWidget *window, *vbox1, *vbox2, *vbox3, *label, *hbox0;
582
GtkWidget *hbox1, *ok_button;
585
window = gtk_dialog_new();
586
gtk_container_border_width(GTK_CONTAINER(window), CONTAINER_BORDER_WIDTH);
587
gtk_window_set_title(GTK_WINDOW(window), _("Warning"));
588
gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
589
vbox1 = GTK_DIALOG(window)->vbox;
590
gtk_widget_show(vbox1);
592
hbox1 = gtk_hbox_new(FALSE, 0);
593
gtk_widget_show(hbox1);
594
gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 10);
595
pixmap = gtk_image_new_from_file(PACKAGE_PREFIX "/share/pixmaps/gq/warning.xpm");
596
gtk_widget_show(pixmap);
597
gtk_box_pack_start(GTK_BOX(hbox1), pixmap, TRUE, TRUE, 10);
599
vbox2 = gtk_vbox_new(FALSE, 0);
600
gtk_widget_show(vbox2);
601
gtk_box_pack_start(GTK_BOX(hbox1), vbox2, TRUE, TRUE, 10);
605
label = gtk_label_new((char *) list->data);
606
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
607
gtk_widget_show(label);
608
gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0);
613
vbox3 = GTK_DIALOG(window)->action_area;
614
gtk_widget_show(vbox3);
616
hbox0 = gtk_hbutton_box_new();
617
gtk_widget_show(hbox0);
618
gtk_box_pack_start(GTK_BOX(vbox3), hbox0, TRUE, TRUE, 0);
620
ok_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
622
g_signal_connect_swapped(ok_button, "clicked",
623
G_CALLBACK(gtk_widget_destroy),
625
gtk_box_pack_start(GTK_BOX(hbox0), ok_button, FALSE, FALSE, 0);
626
GTK_WIDGET_SET_FLAGS(ok_button, GTK_CAN_DEFAULT);
627
gtk_widget_grab_default(ok_button);
628
gtk_widget_show(ok_button);
630
/* what does this mean? PS: 20030928 - FIXME */
631
g_signal_connect_swapped(window, "destroy",
632
G_CALLBACK(gtk_widget_destroy),
635
g_signal_connect_swapped(window, "key_press_event",
636
G_CALLBACK(close_on_esc),
639
gtk_widget_show(window);
641
g_list_free(messages);
646
void single_warning_popup(char *message)
650
msglist = g_list_append(NULL, message);
651
warning_popup(msglist);
656
#ifdef HAVE_LDAP_STR2OBJECTCLASS
657
GList *find_at_by_mr_oid(GqServer *server, const char *oid)
659
GList *list, *srvlist;
660
LDAPAttributeType *at;
663
srvlist = server->ss->at;
665
at = (LDAPAttributeType *) srvlist->data;
667
if( (at->at_equality_oid && !strcasecmp(oid, at->at_equality_oid)) ||
668
(at->at_ordering_oid && !strcasecmp(oid, at->at_ordering_oid)) ||
669
(at->at_substr_oid && !strcasecmp(oid, at->at_substr_oid)) ) {
670
if(at->at_names && at->at_names[0])
671
list = g_list_append(list, at->at_names[0]);
673
list = g_list_append(list, at->at_oid);
675
srvlist = srvlist->next;
681
LDAPAttributeType *find_canonical_at_by_at(struct server_schema *schema,
687
if (!schema) return NULL;
689
for ( atlist = schema->at ; atlist ; atlist = atlist->next ) {
690
LDAPAttributeType *at = (LDAPAttributeType *) atlist->data;
693
for (n = at->at_names ; n && *n ; n++) {
694
/* printf("%s ", *n); */
695
if (strcasecmp(*n, attr) == 0) {
704
GList *find_at_by_s_oid(GqServer *server, const char *oid)
706
GList *list, *srvlist;
707
LDAPAttributeType *at;
710
srvlist = server->ss->at;
712
at = (LDAPAttributeType *) srvlist->data;
714
if(at->at_syntax_oid && !strcasecmp(oid, at->at_syntax_oid)) {
715
if(at->at_names && at->at_names[0])
716
list = g_list_append(list, at->at_names[0]);
718
list = g_list_append(list, at->at_oid);
720
srvlist = srvlist->next;
727
GList *find_mr_by_s_oid(GqServer *server, const char *oid)
729
GList *list, *srvlist;
730
LDAPMatchingRule *mr;
733
srvlist = server->ss->mr;
735
mr = (LDAPMatchingRule *) srvlist->data;
737
if(mr->mr_syntax_oid && !strcasecmp(oid, mr->mr_syntax_oid)) {
738
if(mr->mr_names && mr->mr_names[0])
739
list = g_list_append(list, mr->mr_names[0]);
741
list = g_list_append(list, mr->mr_oid);
743
srvlist = srvlist->next;
750
GList *find_oc_by_at(int error_context,
751
GqServer *server, const char *atname)
753
GList *list, *oclist;
756
struct server_schema *ss = NULL;
760
if (server == NULL) return NULL;
761
ss = get_schema(error_context, server);
762
if (ss == NULL) return NULL;
766
oc = (LDAPObjectClass *) oclist->data;
770
if(oc->oc_at_oids_must) {
772
while(oc->oc_at_oids_must[i] && !found) {
773
if(!strcasecmp(atname, oc->oc_at_oids_must[i])) {
775
if(oc->oc_names && oc->oc_names[0])
776
list = g_list_append(list, oc->oc_names[0]);
778
list = g_list_append(list, oc->oc_oid);
784
if(oc->oc_at_oids_may) {
786
while(oc->oc_at_oids_may[i] && !found) {
787
if(!strcasecmp(atname, oc->oc_at_oids_may[i])) {
789
if(oc->oc_names && oc->oc_names[0])
790
list = g_list_append(list, oc->oc_names[0]);
792
list = g_list_append(list, oc->oc_oid);
798
oclist = oclist->next;
804
const char *find_s_by_at_oid(int error_context, GqServer *server,
808
LDAPAttributeType *at;
810
struct server_schema *ss = NULL;
812
if (server == NULL) return NULL;
813
ss = get_schema(error_context, server);
815
if(ss == NULL || ss->at == NULL)
820
at = (LDAPAttributeType *) srvlist->data;
822
for (c = at->at_names ; c && *c ; c++) {
823
if (!strcasecmp(oid, *c)) {
824
return at->at_syntax_oid;
827
srvlist = srvlist->next;
833
#else /* HAVE_LDAP_STR2OBJECTCLASS */
836
/* fall back to attributeName to find syntax. */
838
struct oid2syntax_t {
843
static struct oid2syntax_t oid2syntax[] = {
844
{ "userPassword", "1.3.6.1.4.1.1466.115.121.1.40" },
845
{ "jpegPhoto", "1.3.6.1.4.1.1466.115.121.1.28" },
846
{ "audio", "1.3.6.1.4.1.1466.115.121.1.4" },
847
{ "photo", "1.3.6.1.4.1.1466.115.121.1.4" },
851
const char *find_s_by_at_oid(GqServer *server, const char *oid)
853
struct oid2syntax_t *os;
854
for (os = oid2syntax ; os->oid ; os++) {
855
if (strcasecmp(os->oid, oid) == 0) return os->syntax;
858
return "1.3.6.1.4.1.1466.115.121.1.3";
862
#endif /* HAVE_LDAP_STR2OBJECTCLASS */
865
struct gq_template *find_template_by_name(const char *templatename)
869
for(I = config->templates ; I ; I = g_list_next(I)) {
870
struct gq_template *template =
871
(struct gq_template *) I->data;
872
if(!strcasecmp(templatename, template->name))
880
void dump_mods(LDAPMod **mods)
888
switch(mod->mod_op) {
889
case LDAP_MOD_ADD: printf("LDAP_MOD_ADD"); break;
890
case LDAP_MOD_DELETE: printf("LDAP_MOD_DELETE"); break;
891
case LDAP_MOD_REPLACE: printf("LDAP_MOD_REPLACE"); break;
892
case LDAP_MOD_BVALUES: printf("LDAP_MOD_BVALUES"); break;
894
printf(" %s\n", mod->mod_type);
896
while(mod->mod_values && mod->mod_values[cval]) {
897
printf("\t%s\n", mod->mod_values[cval]);
913
static struct popup_comm *new_popup_comm()
915
struct popup_comm *n = g_malloc0(sizeof(struct popup_comm));
916
n->ended = n->destroyed = n->rc = 0;
920
static void free_popup_comm(struct popup_comm *c)
926
/* gtk2 checked (multiple destroy callbacks safety), confidence 0.7 */
928
query_destroy(struct popup_comm* comm)
933
gtk_main_quit(); /* quits only nested main loop */
938
query_ok(struct popup_comm* comm)
945
query_cancel(struct popup_comm* comm)
951
/* pops up a dialog to retrieve user data via a GtkEntry. This
952
functions waits for the data and puts it into outbuf.
954
inout_buf afterward points to allocate memory that has to be free'd
955
using g_free. As an input parameter it points to the current value
956
of the information to be entered (if not NULL). The passed-in
957
information will not be changed.
960
int query_popup(const char *title, gchar **inout_buf, gboolean is_password,
961
GtkWidget *modal_for)
963
GtkWidget *window, *vbox1, *vbox2, *label, *inputbox, *button, *hbox0;
965
GtkWidget *f = gtk_grab_get_current();
966
struct popup_comm *comm = new_popup_comm();
968
/* This is a BAD hack - it solves a problem with the query popup
969
dialog that locks up focus handling with all the
970
window-managers I have been able to test this with. Actually,
971
it should be sufficient to let go of the focus, but
972
hiding/showing seems to work... (as I do not know how to
973
release the focus in gtk) - Any gtk Hackers around? */
980
modal_for = gtk_widget_get_toplevel(modal_for);
983
window = gtk_dialog_new();
984
gtk_container_border_width(GTK_CONTAINER(window), CONTAINER_BORDER_WIDTH);
985
gtk_window_set_title(GTK_WINDOW(window), title);
986
gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
987
g_signal_connect_swapped(window, "destroy",
988
G_CALLBACK(query_destroy), comm);
989
g_signal_connect_swapped(window, "key_press_event",
990
G_CALLBACK(close_on_esc),
994
gtk_window_set_modal(GTK_WINDOW(window), TRUE);
995
gtk_window_set_transient_for(GTK_WINDOW(window),
996
GTK_WINDOW(modal_for));
999
vbox1 = GTK_DIALOG(window)->vbox;
1000
gtk_widget_show(vbox1);
1002
label = gtk_label_new(title);
1003
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
1004
gtk_widget_show(label);
1005
gtk_box_pack_start(GTK_BOX(vbox1), label, TRUE, TRUE, 0);
1007
inputbox = gtk_entry_new();
1009
GTK_WIDGET_SET_FLAGS(inputbox, GTK_CAN_FOCUS);
1010
GTK_WIDGET_SET_FLAGS(inputbox, GTK_CAN_DEFAULT);
1012
gtk_entry_set_visibility(GTK_ENTRY(inputbox), FALSE);
1015
if (inout_buf && *inout_buf) {
1017
gtk_editable_insert_text(GTK_EDITABLE(inputbox),
1018
*inout_buf, strlen(*inout_buf), &pos);
1021
gtk_widget_show(inputbox);
1022
g_signal_connect_swapped(inputbox, "activate",
1023
G_CALLBACK(query_ok), comm);
1024
gtk_box_pack_end(GTK_BOX(vbox1), inputbox, TRUE, TRUE, 5);
1026
vbox2 = GTK_DIALOG(window)->action_area;
1027
gtk_container_border_width(GTK_CONTAINER(vbox2), 0);
1028
gtk_widget_show(vbox2);
1030
hbox0 = gtk_hbutton_box_new();
1031
gtk_widget_show(hbox0);
1032
gtk_box_pack_start(GTK_BOX(vbox2), hbox0, TRUE, TRUE, 0);
1034
button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
1036
g_signal_connect_swapped(button, "clicked",
1037
G_CALLBACK(query_ok), comm);
1038
gtk_box_pack_end(GTK_BOX(hbox0), button, FALSE, FALSE, 0);
1039
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1040
GTK_WIDGET_SET_FLAGS(button, GTK_RECEIVES_DEFAULT);
1041
gtk_widget_grab_default(button);
1042
gtk_widget_show(button);
1044
button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1046
g_signal_connect_swapped(button, "clicked",
1047
G_CALLBACK(query_cancel), comm);
1049
gtk_box_pack_end(GTK_BOX(hbox0), button, FALSE, FALSE, 0);
1050
gtk_widget_show(button);
1052
/* gtk_window_set_transient_for(GTK_WINDOW(window), */
1053
/* GTK_WINDOW(getMainWin())); */
1054
gtk_widget_grab_focus(GTK_WIDGET(window));
1055
gtk_window_set_modal(GTK_WINDOW(window), TRUE);
1057
gtk_widget_show(window);
1058
gtk_widget_grab_focus(inputbox);
1063
if (! comm->destroyed && comm->rc) {
1064
*inout_buf = gtk_editable_get_chars(GTK_EDITABLE(inputbox), 0, -1);
1069
if (! comm->destroyed ) {
1070
gtk_widget_destroy(window);
1074
free_popup_comm(comm);
1080
/* pops up a question dialog to ask the user a simple question. This
1081
functions waits for the answer and returns it. */
1083
question_popup(GtkWindow * parent,
1085
gchar const* question)
1089
GtkWidget* f = gtk_grab_get_current();
1091
/* This is a BAD hack - it solves a problem with the query popup
1092
dialog that locks up focus handling with all the
1093
window-managers I have been able to test this with. Actually,
1094
it should be sufficient to let go of the focus, but
1095
hiding/showing seems to work... (as I do not know how to
1096
release the focus in gtk) - Any gtk Hackers around? */
1097
#warning "FIXME: we should be able to remove this one"
1103
window = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL,
1104
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
1106
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(window),
1108
gtk_window_set_title(GTK_WINDOW(window), title);
1109
gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
1111
rc = gtk_dialog_run(GTK_DIALOG(window)) == GTK_RESPONSE_YES;
1112
gtk_widget_destroy(window);
1118
* get all suffixes a server considers itself authorative for.
1121
GList *get_suffixes(int error_context, GqServer *server)
1124
LDAPMessage *res, *e;
1126
int num_suffixes = 0;
1128
char *ldapv3_config[] = {
1133
GList *suffixes = NULL;
1137
if( (ld = open_connection(error_context, server)) == NULL) {
1142
/* try LDAP V3 style config */
1143
statusbar_msg(_("Base search on NULL DN on server '%s'"), gq_server_get_name(server));
1144
msg = ldap_search_s(ld, "", LDAP_SCOPE_BASE, "(objectclass=*)",
1145
ldapv3_config, 0, &res);
1146
if(msg == LDAP_SUCCESS) {
1147
e = ldap_first_entry(ld, res);
1149
vals = ldap_get_values(ld, e, "namingcontexts");
1151
for(i = 0; vals[i]; i++) {
1152
suffixes = g_list_append(suffixes, g_strdup(vals[i]));
1153
/* add_suffix(entry, ctreeroot, node, vals[i]); */
1156
ldap_value_free(vals);
1158
e = ldap_next_entry(ld, e);
1161
} else if (msg == LDAP_SERVER_DOWN) {
1162
server->server_down++;
1163
/* do not try V2 in case of server down problems */
1166
if(num_suffixes == 0) {
1167
/* try Umich style config */
1168
statusbar_msg(_("Base search on cn=config"));
1169
msg = ldap_search_s(ld, "cn=config", LDAP_SCOPE_BASE,
1170
"(objectclass=*)", NULL, 0, &res);
1172
if(msg == LDAP_SUCCESS) {
1173
e = ldap_first_entry(ld, res);
1177
vals = ldap_get_values(ld, e, "database");
1179
for (valptr = vals; valptr && *valptr; valptr++) {
1183
while (p[i] && p[i] != ':')
1185
while (p[i] && (p[i] == ':' || p[i] == ' '))
1188
int len = strlen(p + i);
1190
while (p[i + len - 1] == ' ')
1194
suffixes = g_list_append(suffixes,
1196
/* add_suffix(entry, ctreeroot, node, p + i); */
1200
ldap_value_free(vals);
1202
e = ldap_next_entry(ld, e);
1205
} else if (msg == LDAP_SERVER_DOWN) {
1206
server->server_down++;
1211
/* add the configured base DN if it's a different one */
1212
if(strlen(server->basedn) && (g_list_find_custom(suffixes, server->basedn, (GCompareFunc) strcmp) == NULL)) {
1213
suffixes = g_list_append(suffixes, g_strdup(server->basedn));
1218
close_connection(server, FALSE);
1220
statusbar_msg(ngettext("One suffix found", "%d suffixes found",
1224
return g_list_first(suffixes);
1227
#ifdef HAVE_LDAP_STR2DN
1229
/* OpenLDAP 2.1 both deprecated and broke ldap_explode_dn in one go (I
1230
won't comment on this).
1232
NOTE: this is just a first try to adapt code from Pierangelo
1233
Masarati <masarati@aero.polimi.it>
1237
gq_ldap_explode_dn(gchar const* dn,
1238
int dummy G_GNUC_UNUSED)
1241
#if LDAP_API_VERSION > 2004
1246
GArray* array = NULL;
1247
gchar **retval = NULL;
1249
rc = ldap_str2dn(dn, &parts, LDAP_DN_FORMAT_LDAPV3);
1251
if (rc != LDAP_SUCCESS || parts == NULL) {
1255
array = g_array_new(TRUE, TRUE, sizeof(gchar*));
1256
for(i = 0; parts[i]; i++) {
1259
#if LDAP_API_VERSION > 2004
1264
&part, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
1266
/* don't append the last (empty) part, to be compatible
1267
* to ldap_explode_dn() */
1268
g_array_append_val(array, part);
1271
retval = (gchar**)array->data;
1272
g_array_free(array, FALSE);
1276
void gq_exploded_free(char **exploded_dn)
1278
if (exploded_dn) free(exploded_dn);
1283
static GtkWidget *enable_uline(GtkWidget *label) {
1284
gtk_label_set_use_underline(GTK_LABEL(label), TRUE);
1288
static GtkWidget *bin_enable_uline(GtkWidget *w) {
1290
l = gtk_bin_get_child(GTK_BIN(w));
1296
GtkWidget *gq_label_new(const char *text) {
1297
return gtk_label_new_with_mnemonic(text);
1301
GtkWidget *gq_radio_button_new_with_label(GSList *group,
1304
return bin_enable_uline(gtk_radio_button_new_with_label(group, label));
1307
GtkWidget *gq_menu_item_new_with_label(const gchar *text) {
1308
return bin_enable_uline(gtk_menu_item_new_with_label(text));
1311
GtkWidget *gq_check_button_new_with_label(const gchar *text) {
1312
return bin_enable_uline(gtk_check_button_new_with_label(text));
1315
GtkWidget *gq_button_new_with_label(const gchar *text) {
1316
return bin_enable_uline(gtk_button_new_with_label(text));
1319
GtkWidget *gq_toggle_button_new_with_label(const gchar *text) {
1320
return bin_enable_uline(gtk_toggle_button_new_with_label(text));