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

« back to all changes in this revision

Viewing changes to src/util.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
 
/*
2
 
    GQ -- a GTK-based LDAP client
3
 
    Copyright (C) 1998-2003 Bert Vermeulen
4
 
    Copyright (C) 2002-2003 Peter Stamfest
5
 
 
6
 
    This program is released under the Gnu General Public License with
7
 
    the additional exemption that compiling, linking, and/or using
8
 
    OpenSSL is allowed.
9
 
 
10
 
    This program is free software; you can redistribute it and/or modify
11
 
    it under the terms of the GNU General Public License as published by
12
 
    the Free Software Foundation; either version 2 of the License, or
13
 
    (at your option) any later version.
14
 
 
15
 
    This program is distributed in the hope that it will be useful,
16
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
    GNU General Public License for more details.
19
 
 
20
 
    You should have received a copy of the GNU General Public License
21
 
    along with this program; if not, write to the Free Software
22
 
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 
*/
24
 
 
25
 
/* $Id: util.c 975 2006-09-07 18:44:41Z herzi $ */
26
 
 
27
 
#include <glib.h>
28
 
#include <glib/gi18n.h>
29
 
#include <gtk/gtk.h>
30
 
#include <gdk/gdkkeysyms.h>
31
 
 
32
 
#include <stdio.h>
33
 
#include <unistd.h>
34
 
#include <string.h>
35
 
#include <pwd.h>
36
 
#include <errno.h>
37
 
 
38
 
#ifdef HAVE_CONFIG_H
39
 
# include <config.h>
40
 
#endif /* HAVE_CONFIG_H */
41
 
 
42
 
#include <lber.h>
43
 
#include <ldap.h>
44
 
#ifdef HAVE_LDAP_STR2OBJECTCLASS
45
 
#    include <ldap_schema.h>
46
 
#endif
47
 
#ifdef HAVE_SASL
48
 
#  ifdef HAVE_SASL_H
49
 
#    include <sasl.h>
50
 
#  else
51
 
#    include <sasl/sasl.h>
52
 
#  endif
53
 
#endif
54
 
 
55
 
#ifdef LDAP_OPT_NETWORK_TIMEOUT
56
 
#include <sys/time.h>
57
 
#endif
58
 
 
59
 
#include <glade/glade.h>
60
 
 
61
 
#include "common.h"
62
 
#include "configfile.h"
63
 
#include "errorchain.h"
64
 
#include "gq-keyring.h"
65
 
#include "gq-server-list.h"
66
 
#include "util.h"
67
 
#include "template.h"
68
 
#include "debug.h"
69
 
#include "schema.h"
70
 
#include "encode.h"
71
 
#include "mainwin.h"
72
 
#include "input.h"
73
 
#include "mainwin.h"            /* message_log_append */
74
 
 
75
 
#define TRY_VERSION3 1
76
 
 
77
 
LDAP *open_connection_ex(int open_context,
78
 
                         GqServer *server, int *ldap_errno);
79
 
 
80
 
#ifdef HAVE_SASL
81
 
static int util_ldap_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in)
82
 
{
83
 
     sasl_interact_t *interact = in;
84
 
     GqServer *def = defaults;
85
 
     
86
 
     for (; interact->id != SASL_CB_LIST_END; interact++) {
87
 
        
88
 
             switch (interact->id) {
89
 
                     case SASL_CB_AUTHNAME:
90
 
                             interact->result = def->binddn;
91
 
                             interact->len = strlen(def->binddn);
92
 
                             break;
93
 
        
94
 
                     case SASL_CB_PASS:
95
 
                              if (def->ask_pw) {
96
 
                                      if (def->enteredpw[0]) {
97
 
                                              interact->result = def->enteredpw;
98
 
                                              interact->len = strlen(def->enteredpw);
99
 
                                      }
100
 
                              }
101
 
                              else if (def->bindpw[0]) {
102
 
                                      interact->result = def->bindpw;
103
 
                                      interact->len = strlen(def->bindpw);
104
 
                              }
105
 
                             break;
106
 
             }
107
 
     }
108
 
     return LDAP_SUCCESS;
109
 
}
110
 
#endif
111
 
 
112
 
static int
113
 
do_ldap_auth(LDAP *ld, GqServer *server, int open_context) {
114
 
        char *binddn = NULL;
115
 
        char *bindpw = NULL;
116
 
        int rc = LDAP_SUCCESS;
117
 
 
118
 
        if (server->binddn[0]) {
119
 
                binddn = server->binddn;
120
 
        }
121
 
 
122
 
        /* do not ever use the bindpw if we have turned on to ask
123
 
         * for a password */
124
 
        /* Thanks to Tomas A. Maly <tomas_maly@yahoo.com> for
125
 
         * indirectly causing me to check this area */
126
 
        if (server->ask_pw) {
127
 
                if (server->enteredpw[0])
128
 
                        bindpw = server->enteredpw;
129
 
        }
130
 
        else if (server->bindpw[0])
131
 
                bindpw = server->bindpw;
132
 
 
133
 
        /* take care of special characters... */
134
 
        if (binddn) binddn = encoded_string(binddn);
135
 
        if (bindpw) bindpw = encoded_string(bindpw);
136
 
 
137
 
        switch (server->bindtype) {
138
 
                case BINDTYPE_KERBEROS:
139
 
#ifdef HAVE_KERBEROS
140
 
                        rc = ldap_bind_s(ld, binddn, bindpw, LDAP_AUTH_KRBV4);
141
 
#else
142
 
                        error_push(open_context, 
143
 
                                _("Cannot use Kerberos bind with '%s'.\n"
144
 
                                "GQ was compiled without Kerberos support.\n"
145
 
                                "Run 'configure --help' for more information\n"),
146
 
                                server->name);
147
 
                        statusbar_msg_clear();
148
 
                        /* XXX - should merge kerberos into sasl (gssapi) */
149
 
                        rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
150
 
#endif
151
 
                        break;
152
 
                case BINDTYPE_SASL:
153
 
#ifdef HAVE_SASL
154
 
                        rc = ldap_sasl_interactive_bind_s(ld, NULL, NULL, NULL, NULL, LDAP_SASL_QUIET, util_ldap_sasl_interact, server);
155
 
                        if (rc == LDAP_SUCCESS)
156
 
                                break;
157
 
#else
158
 
                        error_push(open_context, 
159
 
                                _("Cannot use SASL bind with '%s'.\n"
160
 
                                "GQ was compiled without SASL support.\n"
161
 
                                "Run 'configure --help' for more information\n"),
162
 
                                server->name);
163
 
                        statusbar_msg_clear();
164
 
                        rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
165
 
#endif
166
 
                        break;
167
 
                default:
168
 
                        rc = ldap_simple_bind_s(ld, binddn, bindpw);
169
 
                        break;
170
 
        }
171
 
 
172
 
        if (binddn) free(binddn);
173
 
        if (bindpw) free(bindpw);
174
 
        
175
 
        return rc;
176
 
}
177
 
 
178
 
static int do_ldap_connect(LDAP **ld_out, GqServer *server,
179
 
                           int open_context, int flags)
180
 
{
181
 
     LDAP *ld = NULL;
182
 
     char *binddn = NULL, *bindpw = NULL;
183
 
     int rc = LDAP_SUCCESS;
184
 
     int i;
185
 
#ifdef LDAP_OPT_NETWORK_TIMEOUT
186
 
     struct timeval nettimeout;
187
 
#endif
188
 
 
189
 
     *ld_out = NULL;
190
 
 
191
 
     if (g_utf8_strchr(server->ldaphost, -1, ':') != NULL) {
192
 
#ifdef HAVE_LDAP_INITIALIZE
193
 
          rc = ldap_initialize(&ld, server->ldaphost);
194
 
          if (rc != LDAP_SUCCESS) {
195
 
               ld = NULL;
196
 
          }
197
 
 
198
 
          if(!ld) {
199
 
               error_push(open_context, 
200
 
                          _("Failed to initialize LDAP structure for server '%1$s': %2$s."),
201
 
                          server->name,
202
 
                          ldap_err2string(rc));
203
 
          }
204
 
#else
205
 
          ld = NULL;
206
 
          error_push(open_context,
207
 
                     _("Cannot connect to '%s'. No URI support available. Your LDAP toolkit does not support LDAP URIs."),
208
 
                     server->name);
209
 
#endif
210
 
     } else {
211
 
          ld = ldap_init(server->ldaphost, server->ldapport); 
212
 
          if(!ld) {
213
 
               error_push(open_context, 
214
 
                          _("Failed to initialize LDAP structure for server %1$s: %2$s."),
215
 
                          server->name,
216
 
                          strerror(errno));
217
 
          }
218
 
     }
219
 
 
220
 
     if (ld) {
221
 
          server->server_down = 0;
222
 
          server->version = LDAP_VERSION2;
223
 
 
224
 
          /* setup timeouts */
225
 
          i = DEFAULT_LDAP_TIMEOUT;
226
 
          ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &i);
227
 
          
228
 
#ifdef LDAP_OPT_NETWORK_TIMEOUT
229
 
          nettimeout.tv_sec = DEFAULT_NETWORK_TIMEOUT;
230
 
          nettimeout.tv_usec = 0;
231
 
          ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &nettimeout);
232
 
#endif
233
 
 
234
 
#ifndef HAVE_OPENLDAP12
235
 
          if (flags & TRY_VERSION3) {
236
 
               /* try to use LDAP Version 3 */
237
 
               
238
 
               int version = LDAP_VERSION3;
239
 
               if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
240
 
                                   &version) == LDAP_OPT_SUCCESS) {
241
 
                    server->version = LDAP_VERSION3;
242
 
/*             } else { */
243
 
/*                  error_push(open_context, message); */
244
 
/*                  push_ldap_addl_error(ld, open_context); */
245
 
               }
246
 
          }
247
 
#endif
248
 
 
249
 
          if (server->enabletls) {
250
 
#if defined(HAVE_TLS)
251
 
               {
252
 
                    if (server->version != LDAP_VERSION3) {
253
 
                         error_push(open_context,
254
 
                                    _("Server '%s': Couldn't set protocol version to LDAPv3."),
255
 
                                    server->name);
256
 
                    }
257
 
               }
258
 
 
259
 
               /* Let's turn on TLS */
260
 
               rc = ldap_start_tls_s(ld, NULL, NULL);
261
 
               if(rc != LDAP_SUCCESS) {
262
 
                    error_push(open_context,
263
 
                               _("Couldn't enable TLS on the LDAP connection to '%1$s': %2$s"),
264
 
                               server->name,
265
 
                               ldap_err2string(rc));
266
 
                    push_ldap_addl_error(ld, open_context);
267
 
                    ldap_unbind(ld);
268
 
 
269
 
                    return rc;
270
 
               }
271
 
#else
272
 
               error_push(open_context,
273
 
                          _("Cannot use TLS with server '%s'. TLS was not found to be supported by your LDAP libraries.\n"
274
 
                            "See README.TLS for more information.\n"),
275
 
                          server->name);
276
 
#endif /* defined(HAVE_TLS) */
277
 
          }
278
 
 
279
 
          if(server->local_cache_timeout >= 0) {
280
 
#if HAVE_LDAP_CLIENT_CACHE
281
 
               ldap_enable_cache(ld, server->local_cache_timeout, 
282
 
                                 DEFAULT_LOCAL_CACHE_SIZE);
283
 
#else
284
 
               error_push(open_context, 
285
 
                          _("Cannot cache LDAP objects for server '%s'.\n"
286
 
                            "OpenLDAP client-side caching was not enabled.\n"
287
 
                            "See configure --help for more information.\n"),
288
 
                          server->name);
289
 
#endif
290
 
          }
291
 
          
292
 
          /* perform the auth */
293
 
          rc = do_ldap_auth(ld, server, open_context);
294
 
 
295
 
          if (rc != LDAP_SUCCESS) {
296
 
               /* Maybe we cannot use LDAPv3 ... try again */
297
 
               error_push(open_context,
298
 
                          _("Couldn't bind LDAP connection to '%1$s': %2$s"),
299
 
                          server->name, ldap_err2string(rc));
300
 
               push_ldap_addl_error(ld, open_context);
301
 
               statusbar_msg_clear();
302
 
               /* might as well clean this up */
303
 
               ldap_unbind(ld);
304
 
               ld = NULL;
305
 
          } else {
306
 
               /* always store connection handle, regardless of connection
307
 
                  caching -- call close_connection() after each operation
308
 
                  to do the caching thing or not */
309
 
               server->connection = ld;
310
 
               server->missing_closes = 1;
311
 
               server->incarnation++;
312
 
          }
313
 
 
314
 
     }
315
 
 
316
 
     /* experimental referral stuff ... */
317
 
     if (ld) {
318
 
          rc = ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
319
 
 
320
 
          if (rc != LDAP_OPT_SUCCESS ) {
321
 
               error_push(open_context,
322
 
                          _("Could not disable following referrals on connection to server '%s'."), server->name);
323
 
               push_ldap_addl_error(ld, open_context);
324
 
 
325
 
               /* this is not a fatal error, so continue */
326
 
          }
327
 
     }
328
 
 
329
 
     *ld_out = ld;
330
 
     return rc;
331
 
}
332
 
 
333
 
/** Returns a ldapserver object (either an existing or a newly
334
 
    created) usable to search below the base_url. 
335
 
 
336
 
    The server gets looked up in the following way:
337
 
 
338
 
    1) the credentials of the parent server get used with a
339
 
       newly created ldapserver
340
 
 
341
 
    2) The base_url gets looked up as the canonical name. If a match
342
 
       is found and the credentials for this server work a copy of the 
343
 
       thus found object gets returned
344
 
 
345
 
    3) An anonymous bind gets attempted.
346
 
  */
347
 
GqServer*
348
 
get_referral_server(int error_context,
349
 
                    GqServer *parent,
350
 
                    const char *base_url)
351
 
{
352
 
     LDAPURLDesc *desc = NULL;
353
 
     GqServer *newserver = NULL, *s;
354
 
     int ld_err;
355
 
 
356
 
     g_assert(parent);
357
 
 
358
 
     if (ldap_url_parse(base_url, &desc) == 0) {
359
 
          GString *new_uri = g_string_sized_new(strlen(base_url));
360
 
          g_string_sprintf(new_uri, "%s://%s:%d/",
361
 
                           desc->lud_scheme,
362
 
                           desc->lud_host,
363
 
                           desc->lud_port);
364
 
 
365
 
          newserver = gq_server_new();
366
 
 
367
 
          if (! config->never_leak_credentials) {
368
 
               copy_ldapserver(newserver, parent);
369
 
 
370
 
               g_free_and_dup(newserver->name,     new_uri->str);
371
 
               g_free_and_dup(newserver->ldaphost, new_uri->str);
372
 
               g_free_and_dup(newserver->basedn,   desc->lud_dn);
373
 
 
374
 
               /* some sensible settings for the "usual" case:
375
 
                  Anonymous bind. Also show referrals */
376
 
               newserver->ask_pw   = 0;
377
 
               newserver->show_ref = 1;
378
 
               newserver->quiet    = 1;
379
 
 
380
 
               if (open_connection_ex(error_context,
381
 
                                      newserver, &ld_err)) {
382
 
                    close_connection(newserver, FALSE);
383
 
 
384
 
                    statusbar_msg(_("Initialized temporary server-definition '%1$s' from existing server '%2$s'"), new_uri->str, parent->name);
385
 
 
386
 
                    goto done;
387
 
               }
388
 
               if (ld_err == LDAP_SERVER_DOWN) {
389
 
                    goto done;
390
 
               }
391
 
 
392
 
               reset_ldapserver(newserver);
393
 
 
394
 
               /* check: do we have this server around already??? */
395
 
               s = server_by_canon_name(new_uri->str, TRUE);
396
 
 
397
 
               if (s) {
398
 
                    copy_ldapserver(newserver, s);
399
 
 
400
 
                    g_free_and_dup(newserver->name,     new_uri->str);
401
 
                    g_free_and_dup(newserver->ldaphost, new_uri->str);
402
 
                    g_free_and_dup(newserver->basedn,   desc->lud_dn);
403
 
 
404
 
                    /* some sensible settings for the "usual" case:
405
 
                       Anonymous bind. Also show referrals */
406
 
                    newserver->ask_pw   = 0;
407
 
                    newserver->show_ref = 1;
408
 
                    newserver->quiet    = 1;
409
 
 
410
 
                    if (open_connection_ex(error_context,
411
 
                                           newserver, &ld_err)) {
412
 
                         close_connection(newserver, FALSE);
413
 
                         statusbar_msg(_("Initialized temporary server-definition '%1$s' from existing server '%2$s'"), new_uri->str, s->name);
414
 
                         goto done;
415
 
                    }
416
 
                    if (ld_err == LDAP_SERVER_DOWN) {
417
 
                         goto done;
418
 
                    }
419
 
               }
420
 
          }
421
 
 
422
 
          reset_ldapserver(newserver);
423
 
 
424
 
          /* anonymous */
425
 
          copy_ldapserver(newserver, parent);
426
 
          
427
 
          g_free_and_dup(newserver->name,     new_uri->str);
428
 
          g_free_and_dup(newserver->ldaphost, new_uri->str);
429
 
          g_free_and_dup(newserver->basedn,   desc->lud_dn);
430
 
 
431
 
          g_free_and_dup(newserver->binddn, "");
432
 
          g_free_and_dup(newserver->bindpw, "");
433
 
          g_free_and_dup(newserver->enteredpw, "");
434
 
 
435
 
          newserver->bindtype = BINDTYPE_SIMPLE;
436
 
 
437
 
          if (open_connection_ex(error_context, newserver, &ld_err)) {
438
 
               close_connection(newserver, FALSE);
439
 
               statusbar_msg(_("Initialized temporary server-definition '%1$s' from existing server '%2$s'"), new_uri->str, parent->name);
440
 
               goto done;
441
 
          }
442
 
          if (ld_err == LDAP_SERVER_DOWN) {
443
 
               goto done;
444
 
          }
445
 
     }
446
 
 
447
 
 done:
448
 
     if (desc) ldap_free_urldesc(desc);
449
 
     if (newserver) {
450
 
          newserver->quiet = 0;
451
 
          canonicalize_ldapserver(newserver);
452
 
     }
453
 
 
454
 
     return newserver;
455
 
}
456
 
 
457
 
static gboolean
458
 
delete_on_escape(GtkDialog* dialog, GdkEventKey* ev) {
459
 
        if(ev->keyval == GDK_Escape) {
460
 
                gtk_dialog_response(dialog, GTK_RESPONSE_DELETE_EVENT);
461
 
                return TRUE;
462
 
        }
463
 
        return FALSE;
464
 
}
465
 
 
466
 
static gchar*
467
 
get_password_from_dialog(GqServer* server) {
468
 
        GladeXML    * xml = NULL;
469
 
        GtkSizeGroup* group_left  = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
470
 
        GtkSizeGroup* group_right = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
471
 
        GtkWidget   * old_grab = gtk_grab_get_current();
472
 
        gchar const * password = NULL;
473
 
        gchar       * string = NULL;
474
 
 
475
 
        xml = glade_xml_new(PACKAGE_PREFIX "/share/gq/gq.glade", "password_dialog", NULL);
476
 
        if(!xml) {
477
 
                GtkWidget* dlg = gtk_message_dialog_new(NULL, // FIXME: set modal parent
478
 
                                                        GTK_DIALOG_MODAL,
479
 
                                                        GTK_MESSAGE_ERROR,
480
 
                                                        GTK_BUTTONS_CLOSE,
481
 
                                                        "%s", _("The user interface definition could not be "
482
 
                                                                "loaded, please make sure that GQ is correctly "
483
 
                                                                "installed."));
484
 
                gtk_dialog_run(GTK_DIALOG(dlg));
485
 
                gtk_widget_hide(dlg);
486
 
                gtk_widget_destroy(dlg);
487
 
        }
488
 
 
489
 
        // FIXME: the GtkCTree has got the pointer grabbed
490
 
        if(old_grab) {
491
 
                gtk_widget_hide(old_grab);
492
 
                gtk_widget_show(old_grab);
493
 
        }
494
 
 
495
 
        g_signal_connect(glade_xml_get_widget(xml, "password_dialog"), "key-press-event",
496
 
                         G_CALLBACK(delete_on_escape), NULL);
497
 
 
498
 
        gtk_size_group_add_widget(group_left, glade_xml_get_widget(xml, "label_hostname"));
499
 
        gtk_size_group_add_widget(group_left, glade_xml_get_widget(xml, "label_bind_dn"));
500
 
        gtk_size_group_add_widget(group_left, glade_xml_get_widget(xml, "label_bind_mode"));
501
 
        gtk_size_group_add_widget(group_left, glade_xml_get_widget(xml, "label_password"));
502
 
        gtk_size_group_add_widget(group_right, glade_xml_get_widget(xml, "input_hostname"));
503
 
        gtk_size_group_add_widget(group_right, glade_xml_get_widget(xml, "input_bind_dn"));
504
 
        gtk_size_group_add_widget(group_right, glade_xml_get_widget(xml, "input_bind_mode"));
505
 
        gtk_size_group_add_widget(group_right, glade_xml_get_widget(xml, "input_password"));
506
 
 
507
 
        if(!gnome_keyring_is_available()) {
508
 
                gtk_widget_hide(glade_xml_get_widget(xml, "checkbutton_save_password"));
509
 
        }
510
 
 
511
 
        if(server->name && server->ldaphost &&
512
 
           (!strcmp(server->name, server->ldaphost))) {
513
 
                // Server Name and Hostname are equal, do not print twice
514
 
                // TRANSLATORS: "hostname:port"
515
 
                string = g_strdup_printf(_("%s:%d"), server->name, server->ldapport);
516
 
        } else {
517
 
                // TRANSLATORS: "servername (hostname:port)"
518
 
                string = g_strdup_printf(_("%s (%s:%d)"), server->name, server->ldaphost, server->ldapport);
519
 
        }
520
 
        gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(xml, "input_hostname")), string);
521
 
        g_free(string);
522
 
 
523
 
        gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(xml, "input_bind_dn")), server->binddn);
524
 
 
525
 
        // TRANSLATORS: "(Simple,Kerberos,SASL) Authentication"
526
 
        string = g_strdup_printf(_("%s Authentication"), token_bindtype[server->bindtype].keyword);
527
 
        // FIXME: get this translatable as a whole text
528
 
        gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(xml, "input_bind_mode")), string);
529
 
        g_free(string);
530
 
        string = NULL;
531
 
 
532
 
        switch(gtk_dialog_run(GTK_DIALOG(glade_xml_get_widget(xml, "password_dialog")))) {
533
 
        case GTK_RESPONSE_OK:
534
 
                g_free_and_dup(server->bindpw, gtk_entry_get_text(GTK_ENTRY(glade_xml_get_widget(xml, "input_password"))));
535
 
 
536
 
                // FIXME: store password only from successful connections
537
 
                if(gnome_keyring_is_available() &&
538
 
                   gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "checkbutton_save_password")))) {
539
 
                        gq_keyring_save_server_password(server);
540
 
                }
541
 
                break;
542
 
        case GTK_RESPONSE_HELP:
543
 
                // FIXME: add documentation and something about the login dialog
544
 
        default:
545
 
                break;
546
 
        }
547
 
        gtk_widget_destroy(GTK_WIDGET(glade_xml_get_widget(xml, "password_dialog")));
548
 
        g_object_unref(xml);
549
 
        g_object_unref(group_left);
550
 
        g_object_unref(group_right);
551
 
 
552
 
        return string;
553
 
}
554
 
 
555
 
/*
556
 
 * open connection to LDAP server, and store connection for caching
557
 
 */
558
 
LDAP*
559
 
open_connection_ex(int open_context, GqServer *server, int *ldap_errno)
560
 
{
561
 
     LDAP *ld;
562
 
     int rc;
563
 
     GString *message = NULL;
564
 
     int newpw = 0;
565
 
 
566
 
     if (ldap_errno) *ldap_errno = LDAP_SUCCESS;
567
 
     if(!server) return NULL;
568
 
 
569
 
     server->missing_closes++;
570
 
 
571
 
     /* reuse previous connection if available */
572
 
     if(server->connection) {
573
 
          if (server->server_down == 0)
574
 
               return(server->connection);
575
 
          else {
576
 
               /* do not leak file descriptors in case we need to
577
 
                * "rebind" */
578
 
               ldap_unbind(server->connection);
579
 
               server->connection = NULL;
580
 
          }
581
 
     }
582
 
 
583
 
     if (server->ask_pw &&
584
 
         server->binddn[0] && /* makes sense only if we bind as someone */
585
 
         /*      server->bindpw[0] == 0 &&  */
586
 
         server->enteredpw[0] == 0) {
587
 
          char *ret = NULL;
588
 
 
589
 
          if (server->quiet) {
590
 
               return NULL;
591
 
          }
592
 
 
593
 
          ret = gq_keyring_get_password(server);
594
 
 
595
 
          if(!ret) {
596
 
                  ret = get_password_from_dialog(server);
597
 
          }
598
 
 
599
 
          if (ret) { /* FIXME: somehow get modal_for widget */
600
 
               if (ret) {
601
 
                    g_free(server->enteredpw);
602
 
                    server->enteredpw = ret;
603
 
                    newpw = 1;
604
 
               } else {
605
 
                    server->enteredpw[0] = 0;
606
 
               }
607
 
          } else {
608
 
               return NULL;
609
 
          }
610
 
     }
611
 
 
612
 
     if(server->ldapport == 389) {
613
 
          statusbar_msg(_("Connecting to %s"), server->ldaphost);
614
 
     } else {
615
 
          statusbar_msg(_("Connecting to %1$s port %2$d"),
616
 
                        server->ldaphost, server->ldapport);
617
 
     }
618
 
 
619
 
     ld = NULL;
620
 
/*      open_context = error_new_context(_("Error connecting to server")); */
621
 
 
622
 
     rc = do_ldap_connect(&ld, server, open_context,
623
 
                          TRY_VERSION3);
624
 
     if (rc == LDAP_PROTOCOL_ERROR) {
625
 
          /* this might be an indication that the server does not
626
 
             understand LDAP_VERSION3 - retry without trying VERSION3 */
627
 
          rc = do_ldap_connect(&ld, server, open_context, 0);
628
 
          if (rc == LDAP_SUCCESS) error_clear(open_context);
629
 
     } else if (rc == LDAP_INVALID_CREDENTIALS) {
630
 
          /* Should the server configuration pop up? */
631
 
     }
632
 
 
633
 
     /* this is not quite OK: FIXME */
634
 
     if (server->quiet) error_clear(open_context);
635
 
/*      error_flush(open_context); */
636
 
 
637
 
     if (rc != LDAP_SUCCESS) {
638
 
          if (newpw) server->enteredpw[0] = 0;
639
 
     }
640
 
 
641
 
     if (ldap_errno) *ldap_errno = rc;
642
 
 
643
 
     return(ld);
644
 
}
645
 
 
646
 
LDAP *open_connection(int open_context, GqServer *server)
647
 
{
648
 
     return open_connection_ex(open_context, server, NULL);
649
 
}
650
 
 
651
 
/*
652
 
 * called after every set of LDAP operations. This preserves the connection
653
 
 * if caching is enabled for the server. Set always to TRUE if you want to
654
 
 * close the connection regardless of caching.
655
 
 */
656
 
void
657
 
close_connection(GqServer *server, int always)
658
 
{
659
 
        server->missing_closes--;
660
 
 
661
 
        if(server->connection &&
662
 
           ((server->missing_closes == 0 && !server->cacheconn) || always))
663
 
        {
664
 
                /* definitely close this connection */
665
 
                ldap_unbind(server->connection);
666
 
                server->connection = NULL;
667
 
        }
668
 
}
669
 
 
670
 
 
671
 
/*
672
 
 * clear cached server schema
673
 
 */
674
 
void clear_server_schema(GqServer *server)
675
 
{
676
 
#ifdef HAVE_LDAP_STR2OBJECTCLASS
677
 
     GList *list;
678
 
     struct server_schema *ss;
679
 
 
680
 
     if(server->ss) {
681
 
          ss = server->ss;
682
 
 
683
 
          /* objectclasses */
684
 
          list = ss->oc;
685
 
          if(list) {
686
 
               while(list) {
687
 
                    ldap_objectclass_free(list->data);
688
 
                    list = list->next;
689
 
               }
690
 
               g_list_free(ss->oc);
691
 
          }
692
 
 
693
 
          /* attribute types */
694
 
          list = ss->at;
695
 
          if(list) {
696
 
               while(list) {
697
 
                    ldap_attributetype_free(list->data);
698
 
                    list = list->next;
699
 
               }
700
 
               g_list_free(ss->at);
701
 
          }
702
 
 
703
 
          /* matching rules */
704
 
          list = ss->mr;
705
 
          if(list) {
706
 
               while(list) {
707
 
                    ldap_matchingrule_free(list->data);
708
 
                    list = list->next;
709
 
               }
710
 
               g_list_free(ss->mr);
711
 
          }
712
 
 
713
 
          /* syntaxes */
714
 
          list = ss->s;
715
 
          if(list) {
716
 
               while(list) {
717
 
                    ldap_syntax_free(list->data);
718
 
                    list = list->next;
719
 
               }
720
 
               g_list_free(ss->s);
721
 
          }
722
 
 
723
 
          FREE(server->ss, "struct server_schema");
724
 
          server->ss = NULL;
725
 
     }
726
 
     else
727
 
          server->flags &= ~SERVER_HAS_NO_SCHEMA;
728
 
#endif
729
 
 
730
 
}
731
 
 
732
 
 
733
 
/*
734
 
 * delete entry
735
 
 */
736
 
gboolean delete_entry_full(int delete_context,
737
 
                           GqServer *server, char *dn,
738
 
                           gboolean recursive)
739
 
{
740
 
     LDAP *ld;
741
 
     int msg;
742
 
     gboolean rc = TRUE;
743
 
     LDAPControl c;
744
 
     LDAPControl *ctrls[2] = { NULL, NULL } ;
745
 
     LDAPMessage *res = NULL, *e;
746
 
 
747
 
     c.ldctl_oid                = LDAP_CONTROL_MANAGEDSAIT;
748
 
     c.ldctl_value.bv_val       = NULL;
749
 
     c.ldctl_value.bv_len       = 0;
750
 
     c.ldctl_iscritical = 1;
751
 
     
752
 
     ctrls[0] = &c;
753
 
 
754
 
     /* FIXME confirm-mod check here */
755
 
 
756
 
     set_busycursor();
757
 
 
758
 
     if( (ld = open_connection(delete_context, server) ) == NULL) {
759
 
          set_normalcursor();
760
 
          return(FALSE);
761
 
     }
762
 
 
763
 
     if (recursive) {
764
 
          int something_to_do = 1;
765
 
          static char* attrs [] = {"dn", NULL};
766
 
 
767
 
          while (something_to_do) {
768
 
               something_to_do = 0;
769
 
               msg = ldap_search_ext_s(ld, dn,
770
 
                                       LDAP_SCOPE_ONELEVEL,
771
 
                                       "(objectClass=*)",       
772
 
                                       (char **)attrs,  /* attrs */
773
 
                                       1,               /* attrsonly */
774
 
                                       ctrls,           /* serverctrls */
775
 
                                       NULL,            /* clientctrls */
776
 
                                       NULL,            /* timeout */
777
 
                                       LDAP_NO_LIMIT,   /* sizelimit */
778
 
                                       &res);
779
 
 
780
 
               if(msg == LDAP_NOT_SUPPORTED) {
781
 
                    msg = ldap_search_s(ld, dn, LDAP_SCOPE_ONELEVEL,
782
 
                                        "(objectClass=*)",
783
 
                                        (char **) attrs, 1, &res);
784
 
               }
785
 
 
786
 
               if(msg == LDAP_SUCCESS) {
787
 
                    for (e = ldap_first_entry(ld, res); e ; 
788
 
                         e = ldap_next_entry(ld, e)) {
789
 
                         char *dn2 = ldap_get_dn(ld, e);
790
 
                         gboolean delok = delete_entry_full(delete_context, 
791
 
                                                            server, dn2, TRUE);
792
 
                         if (dn2) ldap_memfree(dn2);
793
 
 
794
 
                         if (delok) {
795
 
                              something_to_do = 1;
796
 
                         } else {
797
 
                              goto done;
798
 
                         }
799
 
                    }
800
 
               } else if (msg == LDAP_SERVER_DOWN) {
801
 
                    server->server_down++;
802
 
                    goto done;
803
 
               }
804
 
               if (res) ldap_msgfree(res);
805
 
               res = NULL;
806
 
          }
807
 
     }
808
 
 
809
 
     statusbar_msg(_("Deleting: %s"), dn);
810
 
 
811
 
     msg = ldap_delete_ext_s(ld, dn, ctrls, NULL);
812
 
 
813
 
     if(msg == LDAP_NOT_SUPPORTED) {
814
 
          msg = ldap_delete_s(ld, dn);
815
 
     }
816
 
 
817
 
#if HAVE_LDAP_CLIENT_CACHE
818
 
     ldap_uncache_entry(ld, dn);
819
 
#endif
820
 
 
821
 
     if(msg != LDAP_SUCCESS) {
822
 
          error_push(delete_context, 
823
 
                     "Error deleting DN '%1$s' on '%2$s': %3$s", 
824
 
                     dn, server->name, ldap_err2string(msg));
825
 
          rc = FALSE;
826
 
     }
827
 
     else {
828
 
          statusbar_msg(_("Deleted %s"), dn);
829
 
     }
830
 
 
831
 
 done:
832
 
     if (res) ldap_msgfree(res);
833
 
     set_normalcursor();
834
 
     close_connection(server, FALSE);
835
 
 
836
 
     return(rc);
837
 
}
838
 
 
839
 
 
840
 
gboolean delete_entry(int delete_context,
841
 
                      GqServer *server, char *dn) 
842
 
{
843
 
     return delete_entry_full(delete_context, server, dn, FALSE);
844
 
}
845
 
 
846
 
gboolean do_recursive_delete(int delete_context, 
847
 
                             GqServer *server, char* dn)
848
 
{
849
 
     return delete_entry_full(delete_context, server, dn, TRUE);
850
 
}
851
 
 
852
 
/*
853
 
 * display hourglass cursor on mainwin
854
 
 */
855
 
void set_busycursor(void)
856
 
{
857
 
     GdkCursor *busycursor;
858
 
 
859
 
     busycursor = gdk_cursor_new(GDK_WATCH);
860
 
     gdk_window_set_cursor(mainwin.mainwin->window, busycursor);
861
 
     gdk_cursor_destroy(busycursor);
862
 
 
863
 
}
864
 
 
865
 
 
866
 
/*
867
 
 * set mainwin cursor to default
868
 
 */
869
 
void set_normalcursor(void)
870
 
{
871
 
 
872
 
     gdk_window_set_cursor(mainwin.mainwin->window, NULL);
873
 
 
874
 
}
875
 
 
876
 
/*
877
 
 * callback for key_press_event on a widget, destroys obj if key was esc
878
 
 */
879
 
int close_on_esc(GtkWidget *widget, GdkEventKey *event, gpointer obj)
880
 
{
881
 
     if(event && event->type == GDK_KEY_PRESS && event->keyval == GDK_Escape) {
882
 
          gtk_widget_destroy(GTK_WIDGET(obj));
883
 
          g_signal_stop_emission_by_name(widget, "key_press_event");
884
 
          return(TRUE);
885
 
     }
886
 
 
887
 
     return(FALSE);
888
 
}
889
 
 
890
 
 
891
 
/*
892
 
 * callback for key_press_event on a widget, calls func if key was esc
893
 
 */
894
 
int func_on_esc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window)
895
 
{
896
 
     void (*func)(GtkWidget *);
897
 
 
898
 
     if(event && event->type == GDK_KEY_PRESS && event->keyval == GDK_Escape) {
899
 
          func = gtk_object_get_data(GTK_OBJECT(window), "close_func");
900
 
          func(widget);
901
 
          g_signal_stop_emission_by_name(widget, "key_press_event");
902
 
          return(TRUE);
903
 
     }
904
 
 
905
 
     return(FALSE);
906
 
}
907
 
 
908
 
 
909
 
int tokenize(const struct tokenlist *list, const char *keyword)
910
 
{
911
 
     int i;
912
 
 
913
 
     for(i = 0; list[i].keyword && strlen(list[i].keyword); i++)
914
 
          if(!strcasecmp(list[i].keyword, keyword))
915
 
               return(list[i].token);
916
 
 
917
 
     return(0);
918
 
}
919
 
 
920
 
 
921
 
const char *detokenize(const struct tokenlist *list, int token)
922
 
{
923
 
     int i;
924
 
 
925
 
     for(i = 0; list[i].keyword && strlen(list[i].keyword); i++)
926
 
          if(list[i].token == token)
927
 
               return(list[i].keyword);
928
 
 
929
 
     return(list[0].keyword);
930
 
}
931
 
 
932
 
 
933
 
const void *detokenize_data(const struct tokenlist *list, int token)
934
 
{
935
 
     int i;
936
 
 
937
 
     for(i = 0; strlen(list[i].keyword); i++)
938
 
          if(list[i].token == token)
939
 
               return(list[i].data);
940
 
 
941
 
     return(list[0].data);
942
 
}
943
 
 
944
 
/*
945
 
 * return pointer to username (must be freed)
946
 
 */
947
 
char *get_username(void)
948
 
{
949
 
     struct passwd *pwent;
950
 
     char *username;
951
 
 
952
 
     username = NULL;
953
 
     pwent = getpwuid(getuid());
954
 
     if(pwent && pwent->pw_name)
955
 
          username = strdup(pwent->pw_name);
956
 
     endpwent();
957
 
 
958
 
     return(username);
959
 
}
960
 
 
961
 
 
962
 
/* these should probably belong to struct mainwin_data */
963
 
static guint context = 0, msgid = 0;
964
 
 
965
 
/*
966
 
 * display message in main window's statusbar, and flushes the
967
 
 * GTK event queue
968
 
 */
969
 
void statusbar_msg(const char *fmt, ...)
970
 
{
971
 
     /* do not use g_string_sprintf, as it usually does not support
972
 
        numbered arguments */
973
 
     int len = strlen(fmt) * 2;
974
 
     char *buf;
975
 
     int n;
976
 
 
977
 
     if (len > 0) {
978
 
          for (;;) {
979
 
               va_list ap;
980
 
               buf = g_malloc(len);
981
 
               *buf = 0;
982
 
               
983
 
               va_start(ap, fmt);
984
 
               n = g_vsnprintf(buf, len, fmt, ap);
985
 
               va_end(ap);
986
 
               
987
 
               if (n > len || n == -1) {
988
 
                    g_free(buf);
989
 
                    len *= 2;
990
 
                    continue;
991
 
               }
992
 
               break;
993
 
          } 
994
 
     } else {
995
 
          buf = g_strdup("");
996
 
     }
997
 
 
998
 
     statusbar_msg_clear();
999
 
 
1000
 
     msgid = gtk_statusbar_push(GTK_STATUSBAR(mainwin.statusbar), 
1001
 
                                context, buf);
1002
 
     message_log_append(buf);
1003
 
     g_free(buf);
1004
 
 
1005
 
     /* make sure statusbar gets updated right away */
1006
 
     while(gtk_events_pending())
1007
 
          gtk_main_iteration();
1008
 
}
1009
 
 
1010
 
void statusbar_msg_clear()
1011
 
{
1012
 
     if(!context)
1013
 
          context =
1014
 
               gtk_statusbar_get_context_id(GTK_STATUSBAR(mainwin.statusbar),
1015
 
                                            "mainwin");
1016
 
     if(msgid)
1017
 
          gtk_statusbar_remove(GTK_STATUSBAR(mainwin.statusbar),
1018
 
                               context, msgid);
1019
 
}
1020
 
 
1021
 
/*
1022
 
 * return pointer to GqServer matching the canonical name
1023
 
 */
1024
 
GqServer *server_by_canon_name(const char *name,
1025
 
                                        gboolean include_transient)
1026
 
{
1027
 
     GqServer *server = NULL;
1028
 
     GList *I;
1029
 
 
1030
 
     if(name == NULL || name[0] == '\0')
1031
 
          return NULL;
1032
 
 
1033
 
     server = gq_server_list_get_by_canon_name(gq_server_list_get(), name);
1034
 
     if(!server && include_transient) {
1035
 
          for (I = transient_servers ; I ; I = g_list_next(I)) {
1036
 
               if(!strcmp(((GqServer*)I->data)->canon_name, name)) {
1037
 
                    server = I->data;
1038
 
                    break;
1039
 
               }
1040
 
          }
1041
 
     }
1042
 
     return server;
1043
 
}
1044
 
 
1045
 
gboolean
1046
 
is_transient_server(const GqServer *server) {
1047
 
        g_return_val_if_fail(GQ_IS_SERVER(server), FALSE);
1048
 
        return !gq_server_list_contains(gq_server_list_get(), server);
1049
 
}
1050
 
 
1051
 
/*
1052
 
 * check if entry has a subtree
1053
 
 */
1054
 
int is_leaf_entry(int error_context,
1055
 
                  GqServer *server, char *dn)
1056
 
{
1057
 
     LDAP *ld;
1058
 
     LDAPMessage *res;
1059
 
     int msg, is_leaf, rc;
1060
 
     char *attrs[] = {
1061
 
          LDAP_NO_ATTRS,
1062
 
          NULL
1063
 
     };
1064
 
     LDAPControl c;
1065
 
     LDAPControl *ctrls[2] = { NULL, NULL } ;
1066
 
 
1067
 
     /*  ManageDSAit  */
1068
 
     c.ldctl_oid                = LDAP_CONTROL_MANAGEDSAIT;
1069
 
     c.ldctl_value.bv_val       = NULL;
1070
 
     c.ldctl_value.bv_len       = 0;
1071
 
     c.ldctl_iscritical = 1;
1072
 
     
1073
 
     ctrls[0] = &c;
1074
 
 
1075
 
     is_leaf = 0;
1076
 
 
1077
 
     set_busycursor();
1078
 
 
1079
 
     if( (ld = open_connection(error_context, server) ) == NULL) {
1080
 
          set_normalcursor();
1081
 
          return(-1);
1082
 
     }
1083
 
 
1084
 
     statusbar_msg(_("Checking subtree for %s"), dn);
1085
 
 
1086
 
     rc = ldap_search_ext(ld, dn, LDAP_SCOPE_ONELEVEL, "(objectclass=*)",
1087
 
                           attrs,               /* attrs */
1088
 
                           0,                   /* attrsonly */
1089
 
                           ctrls,               /* serverctrls */
1090
 
                           NULL,                /* clientctrls */
1091
 
                           NULL,                /* timeout */
1092
 
                           LDAP_NO_LIMIT,       /* sizelimit */
1093
 
                           &msg);
1094
 
 
1095
 
     if(rc != -1) {
1096
 
          if( (ldap_result(ld, msg, 0, NULL, &res) != LDAP_RES_SEARCH_ENTRY))
1097
 
               is_leaf = 1;
1098
 
          ldap_msgfree(res);
1099
 
          ldap_abandon(ld, msg);
1100
 
     }
1101
 
 
1102
 
     close_connection(server, FALSE);
1103
 
     set_normalcursor();
1104
 
     statusbar_msg_clear();
1105
 
 
1106
 
     return(is_leaf);
1107
 
}
1108
 
 
1109
 
/*
1110
 
 * check if child is a direct subentry of possible_parent
1111
 
 */
1112
 
gboolean is_direct_parent(char *child, char *possible_parent) 
1113
 
{
1114
 
     /* SHOULD use gq_ldap_explode_dn for this */
1115
 
     char *c = g_utf8_strchr(child, -1, ',');
1116
 
     if (c && (strcasecmp(c + 1, possible_parent) == 0)) return TRUE;
1117
 
     return FALSE;
1118
 
}
1119
 
 
1120
 
/*
1121
 
 * check if child is a (possibly indirect) subentry of possible_ancestor
1122
 
 */
1123
 
gboolean is_ancestor(char *child, char *possible_ancestor) 
1124
 
{
1125
 
     char **rdn = gq_ldap_explode_dn(child, FALSE);
1126
 
     GString *s;
1127
 
     int n;
1128
 
     gboolean rc = FALSE;
1129
 
 
1130
 
     for (n = 0 ; rdn[n] ; n++) {
1131
 
     }
1132
 
 
1133
 
     s = g_string_new("");
1134
 
     for (n-- ; n >= 0 ; n--) {
1135
 
          g_string_insert(s, 0, rdn[n]);
1136
 
          if ((strcasecmp(s->str, possible_ancestor) == 0)) {
1137
 
               rc = TRUE;
1138
 
               break;
1139
 
          }
1140
 
          g_string_insert(s, 0, ",");
1141
 
     }
1142
 
 
1143
 
     g_string_free(s, TRUE);
1144
 
     gq_exploded_free(rdn);
1145
 
 
1146
 
     return rc;
1147
 
}
1148
 
 
1149
 
GList *ar2glist(char *ar[])
1150
 
{
1151
 
     GList *tmp;
1152
 
     int i;
1153
 
 
1154
 
     if(ar == NULL) {
1155
 
          /* gtk_combo_set_popdown_strings() can't handle an
1156
 
             empty list, so give it a list with an empty entry */
1157
 
          tmp = g_list_append(NULL, "");
1158
 
          return(tmp);
1159
 
     }
1160
 
 
1161
 
     tmp = NULL;
1162
 
     i = 0;
1163
 
     while(ar[i])
1164
 
          tmp = g_list_append(tmp, ar[i++]);
1165
 
 
1166
 
     return(tmp);
1167
 
}
1168
 
 
1169
 
 
1170
 
/*
1171
 
 * pops up a warning dialog (with hand icon), and displays all messages in
1172
 
 * the GList , one per line. The GList is freed here.
1173
 
 */
1174
 
void warning_popup(GList *messages)
1175
 
{
1176
 
     GList *list;
1177
 
     GtkWidget *window, *vbox1, *vbox2, *vbox3, *label, *hbox0;
1178
 
     GtkWidget *hbox1, *ok_button;
1179
 
     GtkWidget *pixmap;
1180
 
 
1181
 
     window = gtk_dialog_new();
1182
 
     gtk_container_border_width(GTK_CONTAINER(window), CONTAINER_BORDER_WIDTH);
1183
 
     gtk_window_set_title(GTK_WINDOW(window), _("Warning"));
1184
 
     gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
1185
 
     vbox1 = GTK_DIALOG(window)->vbox;
1186
 
     gtk_widget_show(vbox1);
1187
 
 
1188
 
     hbox1 = gtk_hbox_new(FALSE, 0);
1189
 
     gtk_widget_show(hbox1);
1190
 
     gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 10);
1191
 
     pixmap = gtk_image_new_from_file(PACKAGE_PREFIX "/share/pixmaps/gq/warning.xpm");
1192
 
     gtk_widget_show(pixmap);
1193
 
     gtk_box_pack_start(GTK_BOX(hbox1), pixmap, TRUE, TRUE, 10);
1194
 
 
1195
 
     vbox2 = gtk_vbox_new(FALSE, 0);
1196
 
     gtk_widget_show(vbox2);
1197
 
     gtk_box_pack_start(GTK_BOX(hbox1), vbox2, TRUE, TRUE, 10);
1198
 
 
1199
 
     list = messages;
1200
 
     while(list) {
1201
 
          label = gtk_label_new((char *) list->data);
1202
 
          gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
1203
 
          gtk_widget_show(label);
1204
 
          gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0);
1205
 
          list = list->next;
1206
 
     }
1207
 
 
1208
 
     /* OK button */
1209
 
     vbox3 = GTK_DIALOG(window)->action_area;
1210
 
     gtk_widget_show(vbox3);
1211
 
 
1212
 
     hbox0 = gtk_hbutton_box_new();
1213
 
     gtk_widget_show(hbox0);
1214
 
     gtk_box_pack_start(GTK_BOX(vbox3), hbox0, TRUE, TRUE, 0);
1215
 
 
1216
 
     ok_button = gtk_button_new_from_stock(GTK_STOCK_OK);
1217
 
 
1218
 
     g_signal_connect_swapped(ok_button, "clicked",
1219
 
                               G_CALLBACK(gtk_widget_destroy),
1220
 
                               window);
1221
 
     gtk_box_pack_start(GTK_BOX(hbox0), ok_button, FALSE, FALSE, 0);
1222
 
     GTK_WIDGET_SET_FLAGS(ok_button, GTK_CAN_DEFAULT);
1223
 
     gtk_widget_grab_default(ok_button);
1224
 
     gtk_widget_show(ok_button);
1225
 
 
1226
 
     /* what does this mean? PS: 20030928 - FIXME */
1227
 
     g_signal_connect_swapped(window, "destroy",
1228
 
                               G_CALLBACK(gtk_widget_destroy),
1229
 
                               window);
1230
 
 
1231
 
     g_signal_connect_swapped(window, "key_press_event",
1232
 
                               G_CALLBACK(close_on_esc),
1233
 
                               window);
1234
 
 
1235
 
     gtk_widget_show(window);
1236
 
 
1237
 
     g_list_free(messages);
1238
 
 
1239
 
}
1240
 
 
1241
 
 
1242
 
void single_warning_popup(char *message)
1243
 
{
1244
 
     GList *msglist;
1245
 
 
1246
 
     msglist = g_list_append(NULL, message);
1247
 
     warning_popup(msglist);
1248
 
 
1249
 
}
1250
 
 
1251
 
 
1252
 
#ifdef HAVE_LDAP_STR2OBJECTCLASS
1253
 
GList *find_at_by_mr_oid(GqServer *server, const char *oid)
1254
 
{
1255
 
     GList *list, *srvlist;
1256
 
     LDAPAttributeType *at;
1257
 
 
1258
 
     list = NULL;
1259
 
     srvlist = server->ss->at;
1260
 
     while(srvlist) {
1261
 
          at = (LDAPAttributeType *) srvlist->data;
1262
 
 
1263
 
          if( (at->at_equality_oid && !strcasecmp(oid, at->at_equality_oid)) ||
1264
 
              (at->at_ordering_oid && !strcasecmp(oid, at->at_ordering_oid)) ||
1265
 
              (at->at_substr_oid && !strcasecmp(oid, at->at_substr_oid)) ) {
1266
 
               if(at->at_names && at->at_names[0])
1267
 
                    list = g_list_append(list, at->at_names[0]);
1268
 
               else
1269
 
                    list = g_list_append(list, at->at_oid);
1270
 
          }
1271
 
          srvlist = srvlist->next;
1272
 
     }
1273
 
 
1274
 
     return(list);
1275
 
}
1276
 
 
1277
 
LDAPAttributeType *find_canonical_at_by_at(struct server_schema *schema,
1278
 
                                           const char *attr)
1279
 
{
1280
 
     GList *atlist;
1281
 
     char **n;
1282
 
     
1283
 
     if (!schema) return NULL;
1284
 
     
1285
 
     for ( atlist = schema->at ; atlist ; atlist = atlist->next ) {
1286
 
          LDAPAttributeType *at = (LDAPAttributeType *) atlist->data;
1287
 
          if (!at) continue;
1288
 
          
1289
 
          for (n = at->at_names ; n && *n ; n++) {
1290
 
/*             printf("%s ", *n); */
1291
 
               if (strcasecmp(*n, attr) == 0) {
1292
 
                    /* found! */
1293
 
                    return at;
1294
 
               }
1295
 
          }
1296
 
     }
1297
 
     return NULL;
1298
 
}
1299
 
 
1300
 
GList *find_at_by_s_oid(GqServer *server, const char *oid)
1301
 
{
1302
 
     GList *list, *srvlist;
1303
 
     LDAPAttributeType *at;
1304
 
 
1305
 
     list = NULL;
1306
 
     srvlist = server->ss->at;
1307
 
     while(srvlist) {
1308
 
          at = (LDAPAttributeType *) srvlist->data;
1309
 
 
1310
 
          if(at->at_syntax_oid && !strcasecmp(oid, at->at_syntax_oid)) {
1311
 
               if(at->at_names && at->at_names[0])
1312
 
                    list = g_list_append(list, at->at_names[0]);
1313
 
               else
1314
 
                    list = g_list_append(list, at->at_oid);
1315
 
          }
1316
 
          srvlist = srvlist->next;
1317
 
     }
1318
 
 
1319
 
     return(list);
1320
 
}
1321
 
 
1322
 
 
1323
 
GList *find_mr_by_s_oid(GqServer *server, const char *oid)
1324
 
{
1325
 
     GList *list, *srvlist;
1326
 
     LDAPMatchingRule *mr;
1327
 
 
1328
 
     list = NULL;
1329
 
     srvlist = server->ss->mr;
1330
 
     while(srvlist) {
1331
 
          mr = (LDAPMatchingRule *) srvlist->data;
1332
 
 
1333
 
          if(mr->mr_syntax_oid && !strcasecmp(oid, mr->mr_syntax_oid)) {
1334
 
               if(mr->mr_names && mr->mr_names[0])
1335
 
                    list = g_list_append(list, mr->mr_names[0]);
1336
 
               else
1337
 
                    list = g_list_append(list, mr->mr_oid);
1338
 
          }
1339
 
          srvlist = srvlist->next;
1340
 
     }
1341
 
 
1342
 
     return(list);
1343
 
}
1344
 
 
1345
 
 
1346
 
GList *find_oc_by_at(int error_context,
1347
 
                     GqServer *server, const char *atname)
1348
 
{
1349
 
     GList *list, *oclist;
1350
 
     LDAPObjectClass *oc;
1351
 
     int i, found;
1352
 
     struct server_schema *ss = NULL;
1353
 
 
1354
 
     list = NULL;
1355
 
 
1356
 
     if (server == NULL) return NULL;
1357
 
     ss = get_schema(error_context, server);
1358
 
     if (ss == NULL) return NULL;
1359
 
 
1360
 
     oclist = ss->oc;
1361
 
     while(oclist) {
1362
 
          oc = (LDAPObjectClass *) oclist->data;
1363
 
 
1364
 
          found = 0;
1365
 
 
1366
 
          if(oc->oc_at_oids_must) {
1367
 
               i = 0;
1368
 
               while(oc->oc_at_oids_must[i] && !found) {
1369
 
                    if(!strcasecmp(atname, oc->oc_at_oids_must[i])) {
1370
 
                         found = 1;
1371
 
                         if(oc->oc_names && oc->oc_names[0])
1372
 
                              list = g_list_append(list, oc->oc_names[0]);
1373
 
                         else
1374
 
                              list = g_list_append(list, oc->oc_oid);
1375
 
                    }
1376
 
                    i++;
1377
 
               }
1378
 
          }
1379
 
 
1380
 
          if(oc->oc_at_oids_may) {
1381
 
               i = 0;
1382
 
               while(oc->oc_at_oids_may[i] && !found) {
1383
 
                    if(!strcasecmp(atname, oc->oc_at_oids_may[i])) {
1384
 
                         found = 1;
1385
 
                         if(oc->oc_names && oc->oc_names[0])
1386
 
                              list = g_list_append(list, oc->oc_names[0]);
1387
 
                         else
1388
 
                              list = g_list_append(list, oc->oc_oid);
1389
 
                    }
1390
 
                    i++;
1391
 
               }
1392
 
          }
1393
 
 
1394
 
          oclist = oclist->next;
1395
 
     }
1396
 
 
1397
 
     return(list);
1398
 
}
1399
 
 
1400
 
const char *find_s_by_at_oid(int error_context, GqServer *server,
1401
 
                             const char *oid)
1402
 
{
1403
 
     GList *srvlist;
1404
 
     LDAPAttributeType *at;
1405
 
     char **c;
1406
 
     struct server_schema *ss = NULL;
1407
 
 
1408
 
     if (server == NULL) return NULL;
1409
 
     ss = get_schema(error_context, server);
1410
 
 
1411
 
     if(ss == NULL || ss->at == NULL)
1412
 
          return(NULL);
1413
 
 
1414
 
     srvlist = ss->at;
1415
 
     while(srvlist) {
1416
 
          at = (LDAPAttributeType *) srvlist->data;
1417
 
 
1418
 
          for (c = at->at_names ; c && *c ; c++) {
1419
 
              if (!strcasecmp(oid, *c)) {
1420
 
                  return at->at_syntax_oid;
1421
 
              }
1422
 
          }
1423
 
          srvlist = srvlist->next;
1424
 
     }
1425
 
 
1426
 
     return NULL;
1427
 
}
1428
 
 
1429
 
#else /* HAVE_LDAP_STR2OBJECTCLASS */
1430
 
 
1431
 
 
1432
 
/* fall back to attributeName to find syntax. */
1433
 
 
1434
 
struct oid2syntax_t {
1435
 
     const char *oid;
1436
 
     const char *syntax;
1437
 
};
1438
 
 
1439
 
static struct oid2syntax_t oid2syntax[] = {
1440
 
     { "userPassword", "1.3.6.1.4.1.1466.115.121.1.40" },
1441
 
     { "jpegPhoto", "1.3.6.1.4.1.1466.115.121.1.28" },
1442
 
     { "audio", "1.3.6.1.4.1.1466.115.121.1.4" },
1443
 
     { "photo", "1.3.6.1.4.1.1466.115.121.1.4" },
1444
 
     { NULL, NULL },
1445
 
};
1446
 
 
1447
 
const char *find_s_by_at_oid(GqServer *server, const char *oid)
1448
 
{
1449
 
     struct oid2syntax_t *os;
1450
 
     for (os = oid2syntax ; os->oid ; os++) {
1451
 
          if (strcasecmp(os->oid, oid) == 0) return os->syntax;
1452
 
     }
1453
 
     
1454
 
     return "1.3.6.1.4.1.1466.115.121.1.3";
1455
 
}
1456
 
 
1457
 
 
1458
 
#endif /* HAVE_LDAP_STR2OBJECTCLASS */
1459
 
 
1460
 
 
1461
 
struct gq_template *find_template_by_name(const char *templatename)
1462
 
{
1463
 
     GList *I;
1464
 
 
1465
 
     for(I = config->templates ; I ; I = g_list_next(I)) {
1466
 
          struct gq_template *template = 
1467
 
               (struct gq_template *) I->data;
1468
 
          if(!strcasecmp(templatename, template->name))
1469
 
               return template;
1470
 
     }
1471
 
     return NULL;
1472
 
}
1473
 
 
1474
 
 
1475
 
 
1476
 
void dump_mods(LDAPMod **mods)
1477
 
{
1478
 
     LDAPMod *mod;
1479
 
     int cmod, cval;
1480
 
 
1481
 
     cmod = 0;
1482
 
     while(mods[cmod]) {
1483
 
          mod = mods[cmod];
1484
 
          switch(mod->mod_op) {
1485
 
          case LDAP_MOD_ADD: printf("LDAP_MOD_ADD"); break;
1486
 
          case LDAP_MOD_DELETE: printf("LDAP_MOD_DELETE"); break;
1487
 
          case LDAP_MOD_REPLACE: printf("LDAP_MOD_REPLACE"); break;
1488
 
          case LDAP_MOD_BVALUES: printf("LDAP_MOD_BVALUES"); break;
1489
 
          }
1490
 
          printf(" %s\n", mod->mod_type);
1491
 
          cval = 0;
1492
 
          while(mod->mod_values && mod->mod_values[cval]) {
1493
 
               printf("\t%s\n", mod->mod_values[cval]);
1494
 
               cval++;
1495
 
          }
1496
 
 
1497
 
          cmod++;
1498
 
     }
1499
 
 
1500
 
 
1501
 
}
1502
 
 
1503
 
struct popup_comm {
1504
 
     int destroyed;
1505
 
     int ended;
1506
 
     int rc;
1507
 
};
1508
 
 
1509
 
static struct popup_comm *new_popup_comm() 
1510
 
{
1511
 
     struct popup_comm *n = g_malloc0(sizeof(struct popup_comm));
1512
 
     n->ended = n->destroyed = n->rc = 0;
1513
 
     return n;
1514
 
}
1515
 
 
1516
 
static void free_popup_comm(struct popup_comm *c)
1517
 
{
1518
 
     g_assert(c);
1519
 
     g_free(c);
1520
 
}
1521
 
 
1522
 
/* gtk2 checked (multiple destroy callbacks safety), confidence 0.7 */
1523
 
static void query_destroy(GtkWidget *window, struct popup_comm *comm) {
1524
 
     g_assert(comm);
1525
 
     if (!comm) return;
1526
 
     if (!comm->ended)
1527
 
          gtk_main_quit(); /* quits only nested main loop */
1528
 
     comm->destroyed = 1;
1529
 
}
1530
 
 
1531
 
static void query_ok(GtkWidget *button, struct popup_comm *comm) {
1532
 
     gtk_main_quit();
1533
 
     comm->rc = 1;
1534
 
}
1535
 
 
1536
 
static void query_cancel(GtkWidget *button, struct popup_comm *comm) {
1537
 
     gtk_main_quit();
1538
 
     comm->rc = 0;
1539
 
}
1540
 
 
1541
 
/* pops up a dialog to retrieve user data via a GtkEntry. This
1542
 
   functions waits for the data and puts it into outbuf.
1543
 
 
1544
 
   inout_buf afterward points to allocate memory that has to be free'd
1545
 
   using g_free. As an input parameter it points to the current value
1546
 
   of the information to be entered (if not NULL). The passed-in
1547
 
   information will not be changed.
1548
 
*/
1549
 
 
1550
 
int query_popup(const char *title, gchar **inout_buf, gboolean is_password,
1551
 
                GtkWidget *modal_for)
1552
 
{
1553
 
     GtkWidget *window, *vbox1, *vbox2, *label, *inputbox, *button, *hbox0;
1554
 
     int rc;
1555
 
     GtkWidget *f = gtk_grab_get_current();
1556
 
     struct popup_comm *comm = new_popup_comm();
1557
 
 
1558
 
     /* This is a BAD hack - it solves a problem with the query popup
1559
 
        dialog that locks up focus handling with all the
1560
 
        window-managers I have been able to test this with. Actually,
1561
 
        it should be sufficient to let go of the focus, but
1562
 
        hiding/showing seems to work... (as I do not know how to
1563
 
        release the focus in gtk) - Any gtk Hackers around? */
1564
 
     if (f != NULL) {
1565
 
         gtk_widget_hide(f);
1566
 
         gtk_widget_show(f);
1567
 
     }
1568
 
 
1569
 
     if (modal_for) {
1570
 
          modal_for = gtk_widget_get_toplevel(modal_for);
1571
 
     }
1572
 
 
1573
 
     window = gtk_dialog_new();
1574
 
     gtk_container_border_width(GTK_CONTAINER(window), CONTAINER_BORDER_WIDTH);
1575
 
     gtk_window_set_title(GTK_WINDOW(window), title);
1576
 
     gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
1577
 
     g_signal_connect(window, "destroy",
1578
 
                        G_CALLBACK(query_destroy),
1579
 
                        comm);
1580
 
     g_signal_connect_swapped(window, "key_press_event",
1581
 
                               G_CALLBACK(close_on_esc),
1582
 
                               window);
1583
 
 
1584
 
     if (modal_for) {
1585
 
          gtk_window_set_modal(GTK_WINDOW(window), TRUE);
1586
 
          gtk_window_set_transient_for(GTK_WINDOW(window),
1587
 
                                       GTK_WINDOW(modal_for));
1588
 
     }
1589
 
 
1590
 
     vbox1 = GTK_DIALOG(window)->vbox;
1591
 
     gtk_widget_show(vbox1);
1592
 
 
1593
 
     label = gtk_label_new(title);
1594
 
     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
1595
 
     gtk_widget_show(label);
1596
 
     gtk_box_pack_start(GTK_BOX(vbox1), label, TRUE, TRUE, 0);
1597
 
 
1598
 
     inputbox = gtk_entry_new();
1599
 
 
1600
 
     GTK_WIDGET_SET_FLAGS(inputbox, GTK_CAN_FOCUS);
1601
 
     GTK_WIDGET_SET_FLAGS(inputbox, GTK_CAN_DEFAULT);
1602
 
     if (is_password) {
1603
 
          gtk_entry_set_visibility(GTK_ENTRY(inputbox), FALSE);
1604
 
     }
1605
 
 
1606
 
     if (inout_buf && *inout_buf) {
1607
 
          int pos = 0;
1608
 
          gtk_editable_insert_text(GTK_EDITABLE(inputbox), 
1609
 
                                   *inout_buf, strlen(*inout_buf), &pos);
1610
 
     }
1611
 
 
1612
 
     gtk_widget_show(inputbox);
1613
 
     g_signal_connect(inputbox, "activate",
1614
 
                        G_CALLBACK(query_ok), comm);
1615
 
     gtk_box_pack_end(GTK_BOX(vbox1), inputbox, TRUE, TRUE, 5);
1616
 
 
1617
 
     vbox2 = GTK_DIALOG(window)->action_area;
1618
 
     gtk_container_border_width(GTK_CONTAINER(vbox2), 0);
1619
 
     gtk_widget_show(vbox2);
1620
 
 
1621
 
     hbox0 = gtk_hbutton_box_new();
1622
 
     gtk_widget_show(hbox0);
1623
 
     gtk_box_pack_start(GTK_BOX(vbox2), hbox0, TRUE, TRUE, 0);
1624
 
 
1625
 
     button = gtk_button_new_from_stock(GTK_STOCK_OK);
1626
 
 
1627
 
     g_signal_connect(button, "clicked",
1628
 
                        G_CALLBACK(query_ok), comm);
1629
 
     gtk_box_pack_start(GTK_BOX(hbox0), button, FALSE, FALSE, 0);
1630
 
     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1631
 
     GTK_WIDGET_SET_FLAGS(button, GTK_RECEIVES_DEFAULT);
1632
 
     gtk_widget_grab_default(button);
1633
 
     gtk_widget_show(button);
1634
 
 
1635
 
     button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1636
 
 
1637
 
     g_signal_connect(button, "clicked",
1638
 
                        G_CALLBACK(query_cancel), 
1639
 
                        comm);
1640
 
 
1641
 
     gtk_box_pack_end(GTK_BOX(hbox0), button, FALSE, FALSE, 0);
1642
 
     gtk_widget_show(button);
1643
 
 
1644
 
/*       gtk_window_set_transient_for(GTK_WINDOW(window),  */
1645
 
/*                                GTK_WINDOW(getMainWin())); */
1646
 
     gtk_widget_grab_focus(GTK_WIDGET(window));
1647
 
     gtk_window_set_modal(GTK_WINDOW(window), TRUE);
1648
 
 
1649
 
     gtk_widget_show(window);
1650
 
     gtk_widget_grab_focus(inputbox);
1651
 
 
1652
 
     gtk_main();
1653
 
     comm->ended = 1;
1654
 
 
1655
 
     if (! comm->destroyed && comm->rc) {
1656
 
         *inout_buf = gtk_editable_get_chars(GTK_EDITABLE(inputbox), 0, -1);
1657
 
     } else {
1658
 
         *inout_buf = NULL;
1659
 
     }
1660
 
 
1661
 
     if (! comm->destroyed ) {
1662
 
         gtk_widget_destroy(window);
1663
 
     }
1664
 
 
1665
 
     rc = comm->rc;
1666
 
     free_popup_comm(comm);
1667
 
 
1668
 
     return rc;
1669
 
}
1670
 
 
1671
 
 
1672
 
/* pops up a question dialog to ask the user a simple question. This
1673
 
   functions waits for the answer and returns it. */
1674
 
 
1675
 
int question_popup(const char *title, const char *question)
1676
 
{
1677
 
     GtkWidget *window, *hbox0, *hbox1, *vbox1, *hbox2, *label, *button, *pixmap;
1678
 
     int rc;
1679
 
     GtkWidget *f = gtk_grab_get_current();
1680
 
     struct popup_comm *comm = new_popup_comm();
1681
 
 
1682
 
     /* This is a BAD hack - it solves a problem with the query popup
1683
 
        dialog that locks up focus handling with all the
1684
 
        window-managers I have been able to test this with. Actually,
1685
 
        it should be sufficient to let go of the focus, but
1686
 
        hiding/showing seems to work... (as I do not know how to
1687
 
        release the focus in gtk) - Any gtk Hackers around? */
1688
 
     if (f != NULL) {
1689
 
         gtk_widget_hide(f);
1690
 
         gtk_widget_show(f);
1691
 
     }
1692
 
 
1693
 
     window = gtk_dialog_new();
1694
 
     gtk_container_border_width(GTK_CONTAINER(window), CONTAINER_BORDER_WIDTH);
1695
 
     gtk_window_set_title(GTK_WINDOW(window), title);
1696
 
     gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
1697
 
     g_signal_connect(window, "destroy",
1698
 
                        G_CALLBACK(query_destroy),
1699
 
                        comm);
1700
 
     g_signal_connect_swapped(window, "key_press_event",
1701
 
                               G_CALLBACK(close_on_esc),
1702
 
                               window);
1703
 
 
1704
 
     gtk_widget_show(window);
1705
 
 
1706
 
     vbox1 = GTK_DIALOG(window)->vbox;
1707
 
     gtk_widget_show(vbox1);
1708
 
 
1709
 
     hbox1 = gtk_hbox_new(FALSE, 0);
1710
 
     gtk_widget_show(hbox1);
1711
 
     gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 10);
1712
 
     pixmap = gtk_image_new_from_file(PACKAGE_PREFIX "/share/pixmaps/gq/warning.xpm");
1713
 
     gtk_widget_show(pixmap);
1714
 
     gtk_box_pack_start(GTK_BOX(hbox1), pixmap, TRUE, TRUE, 10);
1715
 
 
1716
 
     label = gtk_label_new(question);
1717
 
     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
1718
 
     gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
1719
 
     gtk_widget_show(label);
1720
 
     gtk_box_pack_end(GTK_BOX(hbox1), label, TRUE, TRUE, 0);
1721
 
 
1722
 
     hbox2 = GTK_DIALOG(window)->action_area;
1723
 
     gtk_widget_show(hbox2);
1724
 
 
1725
 
     hbox0 = gtk_hbutton_box_new();
1726
 
     gtk_widget_show(hbox0);
1727
 
     gtk_box_pack_start(GTK_BOX(hbox2), hbox0, TRUE, TRUE, 0);
1728
 
 
1729
 
     button = gtk_button_new_from_stock(GTK_STOCK_YES);
1730
 
 
1731
 
     g_signal_connect(button, "clicked",
1732
 
                        G_CALLBACK(query_ok), comm);
1733
 
     gtk_box_pack_start(GTK_BOX(hbox0), button, FALSE, FALSE, 0);
1734
 
     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1735
 
     GTK_WIDGET_SET_FLAGS(button, GTK_RECEIVES_DEFAULT);
1736
 
     gtk_widget_grab_default(button);
1737
 
     gtk_widget_show(button);
1738
 
 
1739
 
     button = gtk_button_new_from_stock(GTK_STOCK_NO);
1740
 
 
1741
 
     g_signal_connect(button, "clicked",
1742
 
                        G_CALLBACK(query_cancel), 
1743
 
                        comm);
1744
 
 
1745
 
     gtk_box_pack_end(GTK_BOX(hbox0), button, FALSE, FALSE, 0);
1746
 
     gtk_widget_show(button);
1747
 
 
1748
 
/*       gtk_window_set_transient_for(GTK_WINDOW(window),  */
1749
 
/*                                GTK_WINDOW(getMainWin())); */
1750
 
     gtk_widget_grab_focus(GTK_WIDGET(window));
1751
 
     gtk_window_set_modal(GTK_WINDOW(window), TRUE);
1752
 
 
1753
 
     gtk_widget_show(window);
1754
 
 
1755
 
     gtk_main();
1756
 
     comm->ended = 1;
1757
 
 
1758
 
     if (! comm->destroyed) {
1759
 
         gtk_widget_destroy(window);
1760
 
     }
1761
 
 
1762
 
     rc = comm->rc;
1763
 
     free_popup_comm(comm);
1764
 
 
1765
 
     return rc;
1766
 
}
1767
 
 
1768
 
 
1769
 
/*
1770
 
 * get all suffixes a server considers itself authorative for.
1771
 
 */
1772
 
 
1773
 
GList *get_suffixes(int error_context, GqServer *server)
1774
 
{
1775
 
     LDAP *ld;
1776
 
     LDAPMessage *res, *e;
1777
 
     int msg, i;
1778
 
     int num_suffixes = 0;
1779
 
     char **vals;
1780
 
     char *ldapv3_config[] = {
1781
 
          "namingcontexts",
1782
 
          NULL
1783
 
     };
1784
 
     
1785
 
     GList *suffixes = NULL;
1786
 
     
1787
 
     set_busycursor();
1788
 
     
1789
 
     if( (ld = open_connection(error_context, server)) == NULL) {
1790
 
          set_normalcursor();
1791
 
          return NULL;
1792
 
     }
1793
 
     
1794
 
     /* try LDAP V3 style config */
1795
 
     statusbar_msg(_("Base search on NULL DN on server '%s'"), server->name);
1796
 
     msg = ldap_search_s(ld, "", LDAP_SCOPE_BASE, "(objectclass=*)",
1797
 
                         ldapv3_config, 0, &res);
1798
 
     if(msg == LDAP_SUCCESS) {
1799
 
          e = ldap_first_entry(ld, res);
1800
 
          while (e) {
1801
 
               vals = ldap_get_values(ld, e, "namingcontexts");
1802
 
               if (vals) {
1803
 
                    for(i = 0; vals[i]; i++) {
1804
 
                         suffixes = g_list_append(suffixes, g_strdup(vals[i]));
1805
 
/*                       add_suffix(entry, ctreeroot, node, vals[i]); */
1806
 
                         num_suffixes++;
1807
 
                    }
1808
 
                    ldap_value_free(vals);
1809
 
               }
1810
 
               e = ldap_next_entry(ld, e);
1811
 
          }
1812
 
          ldap_msgfree(res);
1813
 
     } else if (msg == LDAP_SERVER_DOWN) {
1814
 
          server->server_down++;
1815
 
          /* do not try V2 in case of server down problems */
1816
 
     }
1817
 
 
1818
 
     if(num_suffixes == 0) {
1819
 
          /* try Umich style config */
1820
 
          statusbar_msg(_("Base search on cn=config"));
1821
 
          msg = ldap_search_s(ld, "cn=config", LDAP_SCOPE_BASE,
1822
 
                              "(objectclass=*)", NULL, 0, &res);
1823
 
          
1824
 
          if(msg == LDAP_SUCCESS) {
1825
 
               e = ldap_first_entry(ld, res);
1826
 
               while (e) {
1827
 
                    char **valptr;
1828
 
                    
1829
 
                    vals = ldap_get_values(ld, e, "database");
1830
 
                    if (vals) {
1831
 
                         for (valptr = vals; valptr && *valptr; valptr++) {
1832
 
                              char *p = *valptr;
1833
 
                                   
1834
 
                              i = 0;
1835
 
                              while (p[i] && p[i] != ':')
1836
 
                                   i++;
1837
 
                              while (p[i] && (p[i] == ':' || p[i] == ' '))
1838
 
                                   i++;
1839
 
                              if (p[i]) {
1840
 
                                   int len = strlen(p + i);
1841
 
                                        
1842
 
                                   while (p[i + len - 1] == ' ')
1843
 
                                        len--;
1844
 
                                   p[i + len] = '\0';
1845
 
 
1846
 
                                   suffixes = g_list_append(suffixes,
1847
 
                                                            g_strdup(p + i));
1848
 
/*                                 add_suffix(entry, ctreeroot, node, p + i); */
1849
 
                                   num_suffixes++;
1850
 
                              }
1851
 
                         }
1852
 
                         ldap_value_free(vals);
1853
 
                    }
1854
 
                    e = ldap_next_entry(ld, e);
1855
 
               }
1856
 
               ldap_msgfree(res);
1857
 
          } else if (msg == LDAP_SERVER_DOWN) {
1858
 
               server->server_down++;
1859
 
          }
1860
 
     }
1861
 
 
1862
 
 
1863
 
     /* add the configured base DN if it's a different one */
1864
 
     if(strlen(server->basedn) && (g_list_find_custom(suffixes, server->basedn, (GCompareFunc) strcmp) == NULL)) {
1865
 
                suffixes = g_list_append(suffixes, g_strdup(server->basedn));
1866
 
                num_suffixes++;
1867
 
     }
1868
 
 
1869
 
     set_normalcursor();
1870
 
     close_connection(server, FALSE);
1871
 
 
1872
 
     statusbar_msg(ngettext("One suffix found", "%d suffixes found",
1873
 
                            num_suffixes),
1874
 
                   num_suffixes);
1875
 
 
1876
 
     return g_list_first(suffixes);
1877
 
}
1878
 
 
1879
 
#ifdef HAVE_LDAP_STR2DN
1880
 
 
1881
 
/* OpenLDAP 2.1 both deprecated and broke ldap_explode_dn in one go (I
1882
 
   won't comment on this).
1883
 
 
1884
 
   NOTE: this is just a first try to adapt code from Pierangelo
1885
 
   Masarati <masarati@aero.polimi.it>
1886
 
*/
1887
 
 
1888
 
gchar**
1889
 
gq_ldap_explode_dn(gchar const* dn, int dummy) {
1890
 
        int i, rc;
1891
 
#if LDAP_API_VERSION > 2004
1892
 
        LDAPDN parts;
1893
 
#else
1894
 
        LDAPDN *parts;
1895
 
#endif
1896
 
        GArray* array = NULL;
1897
 
        gchar **retval = NULL;
1898
 
 
1899
 
        rc = ldap_str2dn(dn, &parts, LDAP_DN_FORMAT_LDAPV3);
1900
 
 
1901
 
        if (rc != LDAP_SUCCESS || parts == NULL) {
1902
 
                return NULL;
1903
 
        }
1904
 
 
1905
 
        array = g_array_new(TRUE, TRUE, sizeof(gchar*));
1906
 
        for(i = 0; parts[i]; i++) {
1907
 
                gchar* part = NULL;
1908
 
                ldap_rdn2str(
1909
 
#if LDAP_API_VERSION > 2004
1910
 
                        parts[i],
1911
 
#else
1912
 
                        parts[0][i],
1913
 
#endif
1914
 
                        &part, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
1915
 
                if(part && *part) {
1916
 
                        /* don't append the last (empty) part, to be compatible
1917
 
                         * to ldap_explode_dn() */
1918
 
                        g_array_append_val(array, part);
1919
 
                }
1920
 
        }
1921
 
        retval = (gchar**)array->data;
1922
 
        g_array_free(array, FALSE);
1923
 
        return retval;
1924
 
}
1925
 
 
1926
 
void gq_exploded_free(char **exploded_dn)
1927
 
{
1928
 
     if (exploded_dn) free(exploded_dn);
1929
 
}
1930
 
 
1931
 
#endif
1932
 
 
1933
 
static GtkWidget *enable_uline(GtkWidget *label) {
1934
 
     gtk_label_set_use_underline(GTK_LABEL(label), TRUE);
1935
 
     return label;
1936
 
}
1937
 
 
1938
 
static GtkWidget *bin_enable_uline(GtkWidget *w) {
1939
 
     GtkWidget *l;
1940
 
     l = gtk_bin_get_child(GTK_BIN(w));
1941
 
     enable_uline(l);
1942
 
     return w;
1943
 
}
1944
 
 
1945
 
 
1946
 
GtkWidget *gq_label_new(const char *text) {
1947
 
     return gtk_label_new_with_mnemonic(text);
1948
 
}
1949
 
 
1950
 
 
1951
 
GtkWidget *gq_radio_button_new_with_label(GSList *group,
1952
 
                                          const gchar *label) 
1953
 
{
1954
 
     return bin_enable_uline(gtk_radio_button_new_with_label(group, label));
1955
 
}
1956
 
 
1957
 
GtkWidget *gq_menu_item_new_with_label(const gchar *text) {
1958
 
     return bin_enable_uline(gtk_menu_item_new_with_label(text));
1959
 
}
1960
 
 
1961
 
GtkWidget *gq_check_button_new_with_label(const gchar *text) {
1962
 
     return bin_enable_uline(gtk_check_button_new_with_label(text));
1963
 
}
1964
 
 
1965
 
GtkWidget *gq_button_new_with_label(const gchar *text) {
1966
 
     return bin_enable_uline(gtk_button_new_with_label(text));
1967
 
}
1968
 
 
1969
 
GtkWidget *gq_toggle_button_new_with_label(const gchar *text) {
1970
 
     return bin_enable_uline(gtk_toggle_button_new_with_label(text));
1971
 
}
1972
 
 
1973
 
 
1974
 
struct dn_on_server *new_dn_on_server(const char *d,
1975
 
                                      GqServer *s)
1976
 
{
1977
 
     struct dn_on_server *dos = g_malloc0(sizeof(struct dn_on_server));
1978
 
     dos->server = g_object_ref(s);
1979
 
 
1980
 
     if (d) {
1981
 
          dos->dn = g_strdup(d);
1982
 
     } else {
1983
 
          dos->dn = NULL;
1984
 
     }
1985
 
 
1986
 
     return dos;
1987
 
}
1988
 
 
1989
 
void free_dn_on_server(struct dn_on_server *s)
1990
 
{
1991
 
     if (s) {
1992
 
          g_free(s->dn);
1993
 
          s->dn = NULL;
1994
 
          g_object_unref(s->server);
1995
 
          s->server = NULL;
1996
 
 
1997
 
          g_free(s);
1998
 
     }
1999
 
}
2000
 
 
2001
 
 
2002
 
/* 
2003
 
   Local Variables:
2004
 
   c-basic-offset: 5
2005
 
   End:
2006
 
 */