~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Unix SMB/CIFS implementation.
 
3
 *  Join Support (gtk + netapi)
 
4
 *  Copyright (C) Guenther Deschner 2007-2008
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 3 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#define _GNU_SOURCE
 
21
#include <stdio.h>
 
22
#include <sys/types.h>
 
23
#include <inttypes.h>
 
24
#include <stdlib.h>
 
25
#include <unistd.h>
 
26
#include <string.h>
 
27
#include <netdb.h>
 
28
 
 
29
#include <gtk/gtk.h>
 
30
#include <glib/gprintf.h>
 
31
 
 
32
#include <netapi.h>
 
33
 
 
34
#define MAX_CRED_LEN 256
 
35
#define MAX_NETBIOS_NAME_LEN 15
 
36
 
 
37
#define SAMBA_ICON_PATH  "/usr/share/pixmaps/samba/samba.ico"
 
38
#define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
 
39
#define SAMBA_IMAGE_PATH_SMALL "/usr/share/pixmaps/samba/logo-small.png"
 
40
 
 
41
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
 
42
 
 
43
static gboolean verbose = FALSE;
 
44
 
 
45
typedef struct join_state {
 
46
        struct libnetapi_ctx *ctx;
 
47
        GtkWidget *window_main;
 
48
        GtkWidget *window_parent;
 
49
        GtkWidget *window_do_change;
 
50
        GtkWidget *window_creds_prompt;
 
51
        GtkWidget *entry_account;
 
52
        GtkWidget *entry_password;
 
53
        GtkWidget *entry_domain;
 
54
        GtkWidget *entry_ou_list;
 
55
        GtkWidget *entry_workgroup;
 
56
        GtkWidget *button_ok;
 
57
        GtkWidget *button_apply;
 
58
        GtkWidget *button_ok_creds;
 
59
        GtkWidget *button_get_ous;
 
60
        GtkWidget *label_reboot;
 
61
        GtkWidget *label_current_name_buffer;
 
62
        GtkWidget *label_current_name_type;
 
63
        GtkWidget *label_full_computer_name;
 
64
        GtkWidget *label_winbind;
 
65
        uint16_t name_type_initial;
 
66
        uint16_t name_type_new;
 
67
        char *name_buffer_initial;
 
68
        char *name_buffer_new;
 
69
        char *password;
 
70
        char *account;
 
71
        char *comment;
 
72
        char *comment_new;
 
73
        char *my_fqdn;
 
74
        char *my_dnsdomain;
 
75
        char *my_hostname;
 
76
        uint16_t server_role;
 
77
        gboolean settings_changed;
 
78
        gboolean hostname_changed;
 
79
        uint32_t stored_num_ous;
 
80
        char *target_hostname;
 
81
        uid_t uid;
 
82
} join_state;
 
83
 
 
84
static void callback_creds_prompt(GtkWidget *widget,
 
85
                                  gpointer data,
 
86
                                  const char *label_string,
 
87
                                  gpointer cont_fn);
 
88
 
 
89
 
 
90
static void debug(const char *format, ...)
 
91
{
 
92
        va_list args;
 
93
 
 
94
        if (!verbose) {
 
95
                return;
 
96
        }
 
97
 
 
98
        va_start(args, format);
 
99
        g_vprintf(format, args);
 
100
        va_end(args);
 
101
}
 
102
 
 
103
static gboolean callback_delete_event(GtkWidget *widget,
 
104
                                      GdkEvent *event,
 
105
                                      gpointer data)
 
106
{
 
107
        gtk_main_quit();
 
108
        return FALSE;
 
109
}
 
110
 
 
111
static void callback_do_close_data(GtkWidget *widget,
 
112
                                   gpointer data)
 
113
{
 
114
        debug("callback_do_close_data called\n");
 
115
 
 
116
        if (data) {
 
117
                gtk_widget_destroy(GTK_WIDGET(data));
 
118
        }
 
119
}
 
120
 
 
121
static void callback_do_close_widget(GtkWidget *widget,
 
122
                                     gpointer data)
 
123
{
 
124
        debug("callback_do_close_widget called\n");
 
125
 
 
126
        if (widget) {
 
127
                gtk_widget_destroy(widget);
 
128
        }
 
129
}
 
130
 
 
131
static void callback_do_freeauth(GtkWidget *widget,
 
132
                                 gpointer data)
 
133
{
 
134
        struct join_state *state = (struct join_state *)data;
 
135
 
 
136
        debug("callback_do_freeauth called\n");
 
137
 
 
138
        SAFE_FREE(state->account);
 
139
        SAFE_FREE(state->password);
 
140
 
 
141
        if (state->window_creds_prompt) {
 
142
                gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
 
143
                state->window_creds_prompt = NULL;
 
144
        }
 
145
}
 
146
 
 
147
static void callback_do_freeauth_and_close(GtkWidget *widget,
 
148
                                           gpointer data)
 
149
{
 
150
        struct join_state *state = (struct join_state *)data;
 
151
 
 
152
        debug("callback_do_freeauth_and_close called\n");
 
153
 
 
154
        SAFE_FREE(state->account);
 
155
        SAFE_FREE(state->password);
 
156
 
 
157
        if (state->window_creds_prompt) {
 
158
                gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
 
159
                state->window_creds_prompt = NULL;
 
160
        }
 
161
        if (state->window_do_change) {
 
162
                gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
 
163
                state->window_do_change = NULL;
 
164
        }
 
165
}
 
166
 
 
167
static void free_join_state(struct join_state *s)
 
168
{
 
169
        SAFE_FREE(s->name_buffer_initial);
 
170
        SAFE_FREE(s->name_buffer_new);
 
171
        SAFE_FREE(s->password);
 
172
        SAFE_FREE(s->account);
 
173
        SAFE_FREE(s->comment);
 
174
        SAFE_FREE(s->comment_new);
 
175
        SAFE_FREE(s->my_fqdn);
 
176
        SAFE_FREE(s->my_dnsdomain);
 
177
        SAFE_FREE(s->my_hostname);
 
178
}
 
179
 
 
180
static void do_cleanup(struct join_state *state)
 
181
{
 
182
        libnetapi_free(state->ctx);
 
183
        free_join_state(state);
 
184
}
 
185
 
 
186
static void callback_apply_description_change(GtkWidget *widget,
 
187
                                              gpointer data)
 
188
{
 
189
        struct join_state *state = (struct join_state *)data;
 
190
        NET_API_STATUS status = 0;
 
191
        uint32_t parm_err = 0;
 
192
        struct SERVER_INFO_1005 info1005;
 
193
        GtkWidget *dialog;
 
194
 
 
195
        info1005.sv1005_comment = state->comment_new;
 
196
 
 
197
        status = NetServerSetInfo(state->target_hostname,
 
198
                                  1005,
 
199
                                  (uint8_t *)&info1005,
 
200
                                  &parm_err);
 
201
        if (status) {
 
202
                debug("NetServerSetInfo failed with: %s\n",
 
203
                        libnetapi_errstr(status));
 
204
                dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
 
205
                                                GTK_DIALOG_DESTROY_WITH_PARENT,
 
206
                                                GTK_MESSAGE_ERROR,
 
207
                                                GTK_BUTTONS_OK,
 
208
                                                "Failed to change computer description: %s.",
 
209
                                                libnetapi_get_error_string(state->ctx, status));
 
210
                gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
211
                gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
 
212
 
 
213
                g_signal_connect_swapped(dialog, "response",
 
214
                                         G_CALLBACK(gtk_widget_destroy),
 
215
                                         dialog);
 
216
 
 
217
                gtk_widget_show(dialog);
 
218
                return;
 
219
        }
 
220
 
 
221
        gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
 
222
}
 
223
 
 
224
static void callback_do_exit(GtkWidget *widget,
 
225
                             gpointer data)
 
226
{
 
227
#if 0
 
228
        GtkWidget *dialog;
 
229
        gint result;
 
230
#endif
 
231
        struct join_state *state = (struct join_state *)data;
 
232
 
 
233
        if (!state->settings_changed) {
 
234
                callback_delete_event(NULL, NULL, NULL);
 
235
                return;
 
236
        }
 
237
 
 
238
#if 0
 
239
        dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
 
240
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
 
241
                                        GTK_MESSAGE_QUESTION,
 
242
                                        GTK_BUTTONS_YES_NO,
 
243
                                        "You must restart your computer before the new settings will take effect.");
 
244
        gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
245
        result = gtk_dialog_run(GTK_DIALOG(dialog));
 
246
        switch (result) {
 
247
                case GTK_RESPONSE_YES:
 
248
                        g_print("would reboot here\n");
 
249
                        break;
 
250
                case GTK_RESPONSE_NO:
 
251
                default:
 
252
                        break;
 
253
        }
 
254
        if (dialog) {
 
255
                gtk_widget_destroy(GTK_WIDGET(dialog));
 
256
        }
 
257
#endif
 
258
        if (state->window_main) {
 
259
                gtk_widget_destroy(GTK_WIDGET(state->window_main));
 
260
                state->window_main = NULL;
 
261
        }
 
262
        do_cleanup(state);
 
263
        exit(0);
 
264
}
 
265
 
 
266
 
 
267
static void callback_do_reboot(GtkWidget *widget,
 
268
                               gpointer data,
 
269
                               gpointer data2)
 
270
{
 
271
        GtkWidget *dialog;
 
272
        struct join_state *state = (struct join_state *)data2;
 
273
 
 
274
        debug("callback_do_reboot\n");
 
275
 
 
276
        state->settings_changed = TRUE;
 
277
        dialog = gtk_message_dialog_new(GTK_WINDOW(data),
 
278
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
 
279
                                        GTK_MESSAGE_INFO,
 
280
                                        GTK_BUTTONS_OK,
 
281
                                        "You must restart this computer for the changes to take effect.");
 
282
        gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
283
        gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 
284
#if 0
 
285
        g_signal_connect_swapped(dialog, "response",
 
286
                                 G_CALLBACK(gtk_widget_destroy),
 
287
                                 dialog);
 
288
 
 
289
        debug("showing dialog\n");
 
290
        gtk_widget_show(dialog);
 
291
#else
 
292
        gtk_dialog_run(GTK_DIALOG(dialog));
 
293
        gtk_widget_destroy(GTK_WIDGET(dialog));
 
294
#endif
 
295
 
 
296
        gtk_label_set_text(GTK_LABEL(state->label_reboot),
 
297
                           "Changes will take effect after you restart this computer");
 
298
 
 
299
        debug("destroying do_change window\n");
 
300
        gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
 
301
 
 
302
        {
 
303
                uint32_t status;
 
304
                const char *buffer;
 
305
                uint16_t type;
 
306
 
 
307
                status = NetGetJoinInformation(state->target_hostname,
 
308
                                               &buffer,
 
309
                                               &type);
 
310
                if (status != 0) {
 
311
                        g_print("failed to query status\n");
 
312
                        return;
 
313
                }
 
314
 
 
315
                debug("got new status: %s\n", buffer);
 
316
 
 
317
                SAFE_FREE(state->name_buffer_new);
 
318
                state->name_buffer_new = strdup(buffer);
 
319
                state->name_type_new = type;
 
320
                state->name_buffer_initial = strdup(buffer);
 
321
                state->name_type_initial = type;
 
322
                NetApiBufferFree((void *)buffer);
 
323
 
 
324
                gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer),
 
325
                                   state->name_buffer_new);
 
326
                if (state->name_type_new == NetSetupDomainName) {
 
327
                        gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
 
328
                                           "Domain:");
 
329
                } else {
 
330
                        gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
 
331
                                           "Workgroup:");
 
332
                }
 
333
        }
 
334
}
 
335
 
 
336
static void callback_return_username(GtkWidget *widget,
 
337
                                     gpointer data)
 
338
{
 
339
        const gchar *entry_text;
 
340
        struct join_state *state = (struct join_state *)data;
 
341
        debug("callback_return_username called\n");
 
342
        if (!widget) {
 
343
                return;
 
344
        }
 
345
        entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 
346
        if (!entry_text) {
 
347
                return;
 
348
        }
 
349
        debug("callback_return_username: %s\n", entry_text);
 
350
        SAFE_FREE(state->account);
 
351
        state->account = strdup(entry_text);
 
352
}
 
353
 
 
354
static void callback_return_username_and_enter(GtkWidget *widget,
 
355
                                               gpointer data)
 
356
{
 
357
        const gchar *entry_text;
 
358
        struct join_state *state = (struct join_state *)data;
 
359
        if (!widget) {
 
360
                return;
 
361
        }
 
362
        entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 
363
        if (!entry_text) {
 
364
                return;
 
365
        }
 
366
        debug("callback_return_username_and_enter: %s\n", entry_text);
 
367
        SAFE_FREE(state->account);
 
368
        state->account = strdup(entry_text);
 
369
        g_signal_emit_by_name(state->button_ok_creds, "clicked");
 
370
}
 
371
 
 
372
static void callback_return_password(GtkWidget *widget,
 
373
                                     gpointer data)
 
374
{
 
375
        const gchar *entry_text;
 
376
        struct join_state *state = (struct join_state *)data;
 
377
        debug("callback_return_password called\n");
 
378
        if (!widget) {
 
379
                return;
 
380
        }
 
381
        entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 
382
        if (!entry_text) {
 
383
                return;
 
384
        }
 
385
#ifdef DEBUG_PASSWORD
 
386
        debug("callback_return_password: %s\n", entry_text);
 
387
#else
 
388
        debug("callback_return_password: (not printed)\n");
 
389
#endif
 
390
        SAFE_FREE(state->password);
 
391
        state->password = strdup(entry_text);
 
392
}
 
393
 
 
394
static void callback_return_password_and_enter(GtkWidget *widget,
 
395
                                               gpointer data)
 
396
{
 
397
        const gchar *entry_text;
 
398
        struct join_state *state = (struct join_state *)data;
 
399
        if (!widget) {
 
400
                return;
 
401
        }
 
402
        entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 
403
        if (!entry_text) {
 
404
                return;
 
405
        }
 
406
#ifdef DEBUG_PASSWORD
 
407
        debug("callback_return_password_and_enter: %s\n", entry_text);
 
408
#else
 
409
        debug("callback_return_password_and_enter: (not printed)\n");
 
410
#endif
 
411
        SAFE_FREE(state->password);
 
412
        state->password = strdup(entry_text);
 
413
        g_signal_emit_by_name(state->button_ok_creds, "clicked");
 
414
}
 
415
 
 
416
static void callback_do_storeauth(GtkWidget *widget,
 
417
                                  gpointer data)
 
418
{
 
419
        struct join_state *state = (struct join_state *)data;
 
420
 
 
421
        debug("callback_do_storeauth called\n");
 
422
 
 
423
        SAFE_FREE(state->account);
 
424
        SAFE_FREE(state->password);
 
425
 
 
426
        callback_return_username(state->entry_account, (gpointer)state);
 
427
        callback_return_password(state->entry_password, (gpointer)state);
 
428
 
 
429
        if (state->window_creds_prompt) {
 
430
                gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
 
431
                state->window_creds_prompt = NULL;
 
432
        }
 
433
}
 
434
 
 
435
static void callback_continue(GtkWidget *widget,
 
436
                              gpointer data)
 
437
{
 
438
        struct join_state *state = (struct join_state *)data;
 
439
 
 
440
        gtk_widget_grab_focus(GTK_WIDGET(state->button_ok));
 
441
        g_signal_emit_by_name(state->button_ok, "clicked");
 
442
}
 
443
 
 
444
static void callback_do_storeauth_and_continue(GtkWidget *widget,
 
445
                                               gpointer data)
 
446
{
 
447
        callback_do_storeauth(widget, data);
 
448
        callback_continue(NULL, data);
 
449
}
 
450
 
 
451
static void callback_do_storeauth_and_scan(GtkWidget *widget,
 
452
                                           gpointer data)
 
453
{
 
454
        struct join_state *state = (struct join_state *)data;
 
455
        callback_do_storeauth(widget, data);
 
456
        g_signal_emit_by_name(state->button_get_ous, "clicked");
 
457
}
 
458
 
 
459
static void callback_do_hostname_change(GtkWidget *widget,
 
460
                                        gpointer data)
 
461
{
 
462
        GtkWidget *dialog;
 
463
        const char *str = NULL;
 
464
 
 
465
        struct join_state *state = (struct join_state *)data;
 
466
 
 
467
        switch (state->name_type_initial) {
 
468
                case NetSetupDomainName: {
 
469
#if 0
 
470
                        NET_API_STATUS status;
 
471
                        const char *newname;
 
472
                        char *p = NULL;
 
473
 
 
474
                        newname = strdup(gtk_label_get_text(GTK_LABEL(state->label_full_computer_name)));
 
475
                        if (!newname) {
 
476
                                return;
 
477
                        }
 
478
 
 
479
                        p = strchr(newname, '.');
 
480
                        if (p) {
 
481
                                *p = NULL;
 
482
                        }
 
483
 
 
484
                        if (!state->account || !state->password) {
 
485
                                debug("callback_do_hostname_change: no creds yet\n");
 
486
                                callback_creds_prompt(NULL, state,
 
487
                                                      "Enter the name and password of an account with permission to change a computer name in a the domain.",
 
488
                                                      callback_do_storeauth_and_continue);
 
489
                        }
 
490
 
 
491
                        if (!state->account || !state->password) {
 
492
                                debug("callback_do_hostname_change: still no creds???\n");
 
493
                                return;
 
494
                        }
 
495
 
 
496
                        status = NetRenameMachineInDomain(state->target_hostname,
 
497
                                                          newname,
 
498
                                                          state->account,
 
499
                                                          state->password,
 
500
                                                          NETSETUP_ACCT_CREATE);
 
501
                        SAFE_FREE(newname);
 
502
                        /* we renamed the machine in the domain */
 
503
                        if (status == 0) {
 
504
                                return;
 
505
                        }
 
506
                        str = libnetapi_get_error_string(state->ctx, status);
 
507
#else
 
508
                        str = "To be implemented: call NetRenameMachineInDomain\n";
 
509
#endif
 
510
                        break;
 
511
                }
 
512
                case NetSetupWorkgroupName:
 
513
                        str = "To be implemented: call SetComputerNameEx\n";
 
514
                        break;
 
515
                default:
 
516
                        break;
 
517
        }
 
518
 
 
519
        dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 
520
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
 
521
                                        GTK_MESSAGE_ERROR,
 
522
                                        GTK_BUTTONS_CLOSE,
 
523
                                        str);
 
524
 
 
525
        gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
526
        gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
 
527
        g_signal_connect_swapped(dialog, "response",
 
528
                                 G_CALLBACK(gtk_widget_destroy),
 
529
                                 dialog);
 
530
        gtk_widget_show(dialog);
 
531
}
 
532
 
 
533
static void callback_creds_prompt(GtkWidget *widget,
 
534
                                  gpointer data,
 
535
                                  const char *label_string,
 
536
                                  gpointer cont_fn)
 
537
{
 
538
        GtkWidget *window;
 
539
        GtkWidget *box1;
 
540
        GtkWidget *bbox;
 
541
        GtkWidget *button;
 
542
        GtkWidget *label;
 
543
 
 
544
        struct join_state *state = (struct join_state *)data;
 
545
 
 
546
        debug("callback_creds_prompt\n");
 
547
 
 
548
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
549
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
 
550
 
 
551
        gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
 
552
        gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
 
553
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
554
        gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
 
555
        gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
 
556
        gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_do_change));
 
557
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
 
558
 
 
559
        g_signal_connect(G_OBJECT(window), "delete_event",
 
560
                         G_CALLBACK(callback_do_close_widget), NULL);
 
561
 
 
562
        state->window_creds_prompt = window;
 
563
        gtk_container_set_border_width(GTK_CONTAINER(window), 10);
 
564
 
 
565
        box1 = gtk_vbox_new(FALSE, 0);
 
566
 
 
567
        gtk_container_add(GTK_CONTAINER(window), box1);
 
568
 
 
569
        label = gtk_label_new(label_string);
 
570
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
571
        gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 
572
 
 
573
        gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
 
574
 
 
575
        gtk_widget_show(label);
 
576
 
 
577
        /* USER NAME */
 
578
        label = gtk_label_new("User name:");
 
579
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
580
        gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
 
581
        gtk_widget_show(label);
 
582
 
 
583
        state->entry_account = gtk_entry_new();
 
584
        gtk_entry_set_max_length(GTK_ENTRY(state->entry_account), MAX_CRED_LEN);
 
585
        g_signal_connect(G_OBJECT(state->entry_account), "activate",
 
586
                         G_CALLBACK(callback_return_username_and_enter),
 
587
                         (gpointer)state);
 
588
        gtk_editable_select_region(GTK_EDITABLE(state->entry_account),
 
589
                                   0, GTK_ENTRY(state->entry_account)->text_length);
 
590
        gtk_box_pack_start(GTK_BOX(box1), state->entry_account, TRUE, TRUE, 0);
 
591
        gtk_widget_show(state->entry_account);
 
592
 
 
593
        /* PASSWORD */
 
594
        label = gtk_label_new("Password:");
 
595
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
596
        gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
 
597
        gtk_widget_show(label);
 
598
 
 
599
        state->entry_password = gtk_entry_new();
 
600
        gtk_entry_set_max_length(GTK_ENTRY(state->entry_password), MAX_CRED_LEN);
 
601
        gtk_entry_set_visibility(GTK_ENTRY(state->entry_password), FALSE);
 
602
        g_signal_connect(G_OBJECT(state->entry_password), "activate",
 
603
                         G_CALLBACK(callback_return_password_and_enter),
 
604
                         (gpointer)state);
 
605
        gtk_editable_set_editable(GTK_EDITABLE(state->entry_password), TRUE);
 
606
        gtk_editable_select_region(GTK_EDITABLE(state->entry_password),
 
607
                                   0, GTK_ENTRY(state->entry_password)->text_length);
 
608
        gtk_box_pack_start(GTK_BOX(box1), state->entry_password, TRUE, TRUE, 0);
 
609
        gtk_widget_show(state->entry_password);
 
610
 
 
611
        /* BUTTONS */
 
612
        bbox = gtk_hbutton_box_new();
 
613
        gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
 
614
        gtk_container_add(GTK_CONTAINER(box1), bbox);
 
615
        gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
 
616
        gtk_box_set_spacing(GTK_BOX(bbox), 10);
 
617
 
 
618
        state->button_ok_creds = gtk_button_new_from_stock(GTK_STOCK_OK);
 
619
        gtk_widget_grab_focus(GTK_WIDGET(state->button_ok_creds));
 
620
        gtk_container_add(GTK_CONTAINER(bbox), state->button_ok_creds);
 
621
        g_signal_connect(G_OBJECT(state->button_ok_creds), "clicked",
 
622
                         G_CALLBACK(cont_fn),
 
623
                         (gpointer)state);
 
624
        gtk_widget_show(state->button_ok_creds);
 
625
 
 
626
        button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
 
627
        gtk_container_add(GTK_CONTAINER(bbox), button);
 
628
        g_signal_connect(G_OBJECT(button), "clicked",
 
629
                         G_CALLBACK(callback_do_freeauth),
 
630
                         (gpointer)state);
 
631
        gtk_widget_show_all(window);
 
632
}
 
633
 
 
634
static void callback_do_join(GtkWidget *widget,
 
635
                             gpointer data)
 
636
{
 
637
        GtkWidget *dialog;
 
638
 
 
639
        NET_API_STATUS status;
 
640
        const char *err_str = NULL;
 
641
        uint32_t join_flags = 0;
 
642
        uint32_t unjoin_flags = 0;
 
643
        gboolean domain_join = FALSE;
 
644
        gboolean try_unjoin = FALSE;
 
645
        gboolean join_creds_required = TRUE;
 
646
        gboolean unjoin_creds_required = TRUE;
 
647
        const char *new_workgroup_type = NULL;
 
648
        const char *initial_workgroup_type = NULL;
 
649
        const char *account_ou = NULL;
 
650
 
 
651
        struct join_state *state = (struct join_state *)data;
 
652
 
 
653
        if (state->hostname_changed) {
 
654
                callback_do_hostname_change(NULL, state);
 
655
                return;
 
656
        }
 
657
 
 
658
        switch (state->name_type_initial) {
 
659
                case NetSetupWorkgroupName:
 
660
                        initial_workgroup_type = "workgroup";
 
661
                        break;
 
662
                case NetSetupDomainName:
 
663
                        initial_workgroup_type = "domain";
 
664
                        break;
 
665
                default:
 
666
                        break;
 
667
        }
 
668
 
 
669
        switch (state->name_type_new) {
 
670
                case NetSetupWorkgroupName:
 
671
                        new_workgroup_type = "workgroup";
 
672
                        break;
 
673
                case NetSetupDomainName:
 
674
                        new_workgroup_type = "domain";
 
675
                        break;
 
676
                default:
 
677
                        break;
 
678
        }
 
679
 
 
680
        account_ou = gtk_combo_box_get_active_text(GTK_COMBO_BOX(state->entry_ou_list));
 
681
        if (account_ou && strlen(account_ou) == 0) {
 
682
                account_ou = NULL;
 
683
        }
 
684
 
 
685
        if ((state->name_type_initial != NetSetupDomainName) &&
 
686
            (state->name_type_new != NetSetupDomainName)) {
 
687
                join_creds_required = FALSE;
 
688
                unjoin_creds_required = FALSE;
 
689
        }
 
690
 
 
691
        if (state->name_type_new == NetSetupDomainName) {
 
692
                domain_join = TRUE;
 
693
                join_creds_required = TRUE;
 
694
                join_flags = NETSETUP_JOIN_DOMAIN |
 
695
                             NETSETUP_ACCT_CREATE |
 
696
                             NETSETUP_DOMAIN_JOIN_IF_JOINED; /* for testing */
 
697
        }
 
698
 
 
699
        if ((state->name_type_initial == NetSetupDomainName) &&
 
700
            (state->name_type_new == NetSetupWorkgroupName)) {
 
701
                try_unjoin = TRUE;
 
702
                unjoin_creds_required = TRUE;
 
703
                join_creds_required = FALSE;
 
704
                unjoin_flags = NETSETUP_JOIN_DOMAIN |
 
705
                               NETSETUP_ACCT_DELETE |
 
706
                               NETSETUP_IGNORE_UNSUPPORTED_FLAGS;
 
707
        }
 
708
 
 
709
        if (try_unjoin) {
 
710
 
 
711
                debug("callback_do_join: Unjoining\n");
 
712
 
 
713
                if (unjoin_creds_required) {
 
714
                        if (!state->account || !state->password) {
 
715
                                debug("callback_do_join: no creds yet\n");
 
716
                                callback_creds_prompt(NULL, state,
 
717
                                                      "Enter the name and password of an account with permission to leave the domain.",
 
718
                                                      callback_do_storeauth_and_continue);
 
719
                        }
 
720
 
 
721
                        if (!state->account || !state->password) {
 
722
                                debug("callback_do_join: still no creds???\n");
 
723
                                return;
 
724
                        }
 
725
                }
 
726
 
 
727
                status = NetUnjoinDomain(state->target_hostname,
 
728
                                         state->account,
 
729
                                         state->password,
 
730
                                         unjoin_flags);
 
731
                if (status != 0) {
 
732
                        callback_do_freeauth(NULL, state);
 
733
                        err_str = libnetapi_get_error_string(state->ctx, status);
 
734
                        g_print("callback_do_join: failed to unjoin (%s)\n",
 
735
                                err_str);
 
736
#if 0
 
737
 
 
738
        /* in fact we shouldn't annoy the user with an error message here */
 
739
 
 
740
                        dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 
741
                                                        GTK_DIALOG_DESTROY_WITH_PARENT,
 
742
                                                        GTK_MESSAGE_ERROR,
 
743
                                                        GTK_BUTTONS_CLOSE,
 
744
                                                        "The following error occured attempting to unjoin the %s: \"%s\": %s",
 
745
                                                        initial_workgroup_type,
 
746
                                                        state->name_buffer_initial,
 
747
                                                        err_str);
 
748
                        gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
749
                        gtk_dialog_run(GTK_DIALOG(dialog));
 
750
                        gtk_widget_destroy(dialog);
 
751
#endif
 
752
                }
 
753
 
 
754
        }
 
755
 
 
756
        /* before prompting for creds, make sure we can find a dc */
 
757
 
 
758
        if (domain_join) {
 
759
 
 
760
                struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
 
761
 
 
762
                status = DsGetDcName(NULL,
 
763
                                     state->name_buffer_new,
 
764
                                     NULL,
 
765
                                     NULL,
 
766
                                     0,
 
767
                                     &dc_info);
 
768
                if (status != 0) {
 
769
                        err_str = libnetapi_get_error_string(state->ctx, status);
 
770
                        g_print("callback_do_join: failed find dc (%s)\n", err_str);
 
771
 
 
772
                        dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 
773
                                                        GTK_DIALOG_DESTROY_WITH_PARENT,
 
774
                                                        GTK_MESSAGE_ERROR,
 
775
                                                        GTK_BUTTONS_CLOSE,
 
776
                                                        "Failed to find a domain controller for domain: \"%s\": %s",
 
777
                                                        state->name_buffer_new,
 
778
                                                        err_str);
 
779
 
 
780
                        gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
781
                        gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 
782
                        g_signal_connect_swapped(dialog, "response",
 
783
                                                 G_CALLBACK(gtk_widget_destroy),
 
784
                                                 dialog);
 
785
 
 
786
                        gtk_widget_show(dialog);
 
787
 
 
788
                        return;
 
789
                }
 
790
        }
 
791
 
 
792
        if (join_creds_required) {
 
793
                if (!state->account || !state->password) {
 
794
                        debug("callback_do_join: no creds yet\n");
 
795
                        callback_creds_prompt(NULL, state,
 
796
                                              "Enter the name and password of an account with permission to join the domain.",
 
797
                                              callback_do_storeauth_and_continue);
 
798
                }
 
799
 
 
800
                if (!state->account || !state->password) {
 
801
                        debug("callback_do_join: still no creds???\n");
 
802
                        return;
 
803
                }
 
804
        }
 
805
 
 
806
        debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
 
807
                new_workgroup_type,
 
808
                state->name_buffer_new,
 
809
                join_flags);
 
810
        if (domain_join) {
 
811
                debug("as %s ", state->account);
 
812
#ifdef DEBUG_PASSWORD
 
813
                debug("with %s ", state->password);
 
814
#endif
 
815
        }
 
816
        debug("\n");
 
817
 
 
818
        status = NetJoinDomain(state->target_hostname,
 
819
                               state->name_buffer_new,
 
820
                               account_ou,
 
821
                               state->account,
 
822
                               state->password,
 
823
                               join_flags);
 
824
        if (status != 0) {
 
825
                callback_do_freeauth(NULL, state);
 
826
                err_str = libnetapi_get_error_string(state->ctx, status);
 
827
                g_print("callback_do_join: failed to join (%s)\n", err_str);
 
828
 
 
829
                dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 
830
                                                GTK_DIALOG_DESTROY_WITH_PARENT,
 
831
                                                GTK_MESSAGE_ERROR,
 
832
                                                GTK_BUTTONS_CLOSE,
 
833
                                                "The following error occured attempting to join the %s: \"%s\": %s",
 
834
                                                new_workgroup_type,
 
835
                                                state->name_buffer_new,
 
836
                                                err_str);
 
837
 
 
838
                gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
839
                gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 
840
                g_signal_connect_swapped(dialog, "response",
 
841
                                         G_CALLBACK(gtk_widget_destroy),
 
842
                                         dialog);
 
843
 
 
844
                gtk_widget_show(dialog);
 
845
 
 
846
                return;
 
847
        }
 
848
 
 
849
        debug("callback_do_join: Successfully joined %s\n",
 
850
                new_workgroup_type);
 
851
 
 
852
        callback_do_freeauth(NULL, state);
 
853
        dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 
854
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
 
855
                                        GTK_MESSAGE_INFO,
 
856
                                        GTK_BUTTONS_OK,
 
857
                                        "Welcome to the %s %s.",
 
858
                                        state->name_buffer_new,
 
859
                                        new_workgroup_type);
 
860
 
 
861
        gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
862
        gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 
863
        gtk_dialog_run(GTK_DIALOG(dialog));
 
864
        gtk_widget_destroy(dialog);
 
865
 
 
866
        callback_do_reboot(NULL, state->window_parent, state);
 
867
}
 
868
 
 
869
static void callback_enter_hostname_and_unlock(GtkWidget *widget,
 
870
                                               gpointer data)
 
871
{
 
872
        const gchar *entry_text = NULL;
 
873
        char *str = NULL;
 
874
        struct join_state *state = (struct join_state *)data;
 
875
 
 
876
        entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 
877
        debug("callback_enter_hostname_and_unlock: %s\n", entry_text);
 
878
        if (!entry_text || entry_text[0] == 0) {
 
879
                state->hostname_changed = FALSE;
 
880
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 
881
                gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), "");
 
882
                return;
 
883
        }
 
884
        if (strcasecmp(state->my_hostname, entry_text) == 0) {
 
885
                state->hostname_changed = FALSE;
 
886
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 
887
                /* return; */
 
888
        } else {
 
889
                state->hostname_changed = TRUE;
 
890
        }
 
891
 
 
892
        if (state->name_type_initial == NetSetupDomainName) {
 
893
                if (asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain) == -1) {
 
894
                        return;
 
895
                }
 
896
        } else {
 
897
                if (asprintf(&str, "%s.", entry_text) == -1) {
 
898
                        return;
 
899
                }
 
900
        }
 
901
        gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
 
902
        free(str);
 
903
 
 
904
        if (state->hostname_changed && entry_text && entry_text[0] != 0 && entry_text[0] != '.') {
 
905
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
 
906
        }
 
907
}
 
908
 
 
909
static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
 
910
                                                           gpointer data)
 
911
{
 
912
        const gchar *entry_text = NULL;
 
913
        struct join_state *state = (struct join_state *)data;
 
914
        int string_unchanged = FALSE;
 
915
 
 
916
        entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 
917
        debug("callback_enter_computer_description_and_unlock: %s\n",
 
918
                entry_text);
 
919
#if 0
 
920
        if (!entry_text || entry_text[0] == 0) {
 
921
                string_unchanged = 1;
 
922
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
 
923
                                         FALSE);
 
924
                return;
 
925
        }
 
926
#endif
 
927
        if (entry_text && state->comment && strcasecmp(state->comment, entry_text) == 0) {
 
928
                string_unchanged = TRUE;
 
929
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
 
930
                                         FALSE);
 
931
                return;
 
932
        }
 
933
 
 
934
        gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), TRUE);
 
935
        SAFE_FREE(state->comment_new);
 
936
        state->comment_new = strdup(entry_text);
 
937
 
 
938
}
 
939
 
 
940
 
 
941
static void callback_enter_workgroup_and_unlock(GtkWidget *widget,
 
942
                                                gpointer data)
 
943
{
 
944
        const gchar *entry_text = NULL;
 
945
        struct join_state *state = (struct join_state *)data;
 
946
 
 
947
        entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 
948
        debug("callback_enter_workgroup_and_unlock: %s\n", entry_text);
 
949
        if (!entry_text || entry_text[0] == 0) {
 
950
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 
951
                return;
 
952
        }
 
953
        if ((strcasecmp(state->name_buffer_initial, entry_text) == 0) &&
 
954
            (state->name_type_initial == NetSetupWorkgroupName)) {
 
955
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 
956
                return;
 
957
        }
 
958
        gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
 
959
        SAFE_FREE(state->name_buffer_new);
 
960
        state->name_buffer_new = strdup(entry_text);
 
961
        state->name_type_new = NetSetupWorkgroupName;
 
962
}
 
963
 
 
964
static void callback_enter_domain_and_unlock(GtkWidget *widget,
 
965
                                             gpointer data)
 
966
{
 
967
        const gchar *entry_text = NULL;
 
968
        struct join_state *state = (struct join_state *)data;
 
969
 
 
970
        entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 
971
        debug("callback_enter_domain_and_unlock: %s\n", entry_text);
 
972
        if (!entry_text || entry_text[0] == 0) {
 
973
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 
974
                return;
 
975
        }
 
976
        if ((strcasecmp(state->name_buffer_initial, entry_text) == 0) &&
 
977
            (state->name_type_initial == NetSetupDomainName)) {
 
978
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 
979
                return;
 
980
        }
 
981
        gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
 
982
        gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), TRUE);
 
983
        gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), TRUE);
 
984
        SAFE_FREE(state->name_buffer_new);
 
985
        state->name_buffer_new = strdup(entry_text);
 
986
        state->name_type_new = NetSetupDomainName;
 
987
}
 
988
 
 
989
static void callback_apply_continue(GtkWidget *widget,
 
990
                                    gpointer data)
 
991
{
 
992
        struct join_state *state = (struct join_state *)data;
 
993
 
 
994
        gtk_widget_grab_focus(GTK_WIDGET(state->button_apply));
 
995
        g_signal_emit_by_name(state->button_apply, "clicked");
 
996
}
 
997
 
 
998
static void callback_do_join_workgroup(GtkWidget *widget,
 
999
                                       gpointer data)
 
1000
{
 
1001
        struct join_state *state = (struct join_state *)data;
 
1002
        debug("callback_do_join_workgroup choosen\n");
 
1003
        gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
 
1004
        gtk_widget_grab_focus(GTK_WIDGET(state->entry_workgroup));
 
1005
        gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
 
1006
        gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), FALSE);
 
1007
        gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
 
1008
        callback_enter_workgroup_and_unlock(state->entry_workgroup, state); /* TEST */
 
1009
}
 
1010
 
 
1011
static void callback_do_join_domain(GtkWidget *widget,
 
1012
                                    gpointer data)
 
1013
{
 
1014
        struct join_state *state = (struct join_state *)data;
 
1015
        debug("callback_do_join_domain choosen\n");
 
1016
        gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), TRUE);
 
1017
        gtk_widget_grab_focus(GTK_WIDGET(state->entry_domain));
 
1018
        gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), FALSE);
 
1019
        callback_enter_domain_and_unlock(state->entry_domain, state); /* TEST */
 
1020
}
 
1021
 
 
1022
static void callback_do_getous(GtkWidget *widget,
 
1023
                               gpointer data)
 
1024
{
 
1025
        NET_API_STATUS status;
 
1026
        uint32_t num_ous = 0;
 
1027
        const char **ous = NULL;
 
1028
        int i;
 
1029
        const char *domain = NULL;
 
1030
        struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
 
1031
        const char *err_str = NULL;
 
1032
        GtkWidget *dialog;
 
1033
 
 
1034
        struct join_state *state = (struct join_state *)data;
 
1035
 
 
1036
        debug("callback_do_getous called\n");
 
1037
 
 
1038
        domain = state->name_buffer_new ? state->name_buffer_new : state->name_buffer_initial;
 
1039
 
 
1040
        status = DsGetDcName(NULL,
 
1041
                             domain,
 
1042
                             NULL,
 
1043
                             NULL,
 
1044
                             0,
 
1045
                             &dc_info);
 
1046
        if (status != 0) {
 
1047
                err_str = libnetapi_get_error_string(state->ctx, status);
 
1048
                g_print("callback_do_getous: failed find dc (%s)\n", err_str);
 
1049
 
 
1050
                dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 
1051
                                                GTK_DIALOG_DESTROY_WITH_PARENT,
 
1052
                                                GTK_MESSAGE_ERROR,
 
1053
                                                GTK_BUTTONS_CLOSE,
 
1054
                                                "Failed to find a domain controller for domain: \"%s\": %s",
 
1055
                                                domain,
 
1056
                                                err_str);
 
1057
 
 
1058
                gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
1059
                gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 
1060
                g_signal_connect_swapped(dialog, "response",
 
1061
                                         G_CALLBACK(gtk_widget_destroy),
 
1062
                                         dialog);
 
1063
 
 
1064
                gtk_widget_show(dialog);
 
1065
 
 
1066
                return;
 
1067
        }
 
1068
 
 
1069
        if (!state->account || !state->password) {
 
1070
                debug("callback_do_getous: no creds yet\n");
 
1071
                callback_creds_prompt(NULL, state,
 
1072
                                      "Enter the name and password of an account with permission to join the domain.",
 
1073
                                      callback_do_storeauth_and_scan);
 
1074
        }
 
1075
 
 
1076
        if (!state->account || !state->password) {
 
1077
                debug("callback_do_getous: still no creds ???\n");
 
1078
                return;
 
1079
        }
 
1080
 
 
1081
        status = NetGetJoinableOUs(state->target_hostname,
 
1082
                                   domain,
 
1083
                                   state->account,
 
1084
                                   state->password,
 
1085
                                   &num_ous, &ous);
 
1086
        if (status != NET_API_STATUS_SUCCESS) {
 
1087
                callback_do_freeauth(NULL, state);
 
1088
                debug("failed to call NetGetJoinableOUs: %s\n",
 
1089
                        libnetapi_get_error_string(state->ctx, status));
 
1090
                dialog = gtk_message_dialog_new(NULL,
 
1091
                                                GTK_DIALOG_DESTROY_WITH_PARENT,
 
1092
                                                GTK_MESSAGE_INFO,
 
1093
                                                GTK_BUTTONS_OK,
 
1094
                                                "Failed to query joinable OUs: %s",
 
1095
                                                libnetapi_get_error_string(state->ctx, status));
 
1096
                gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
1097
                gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 
1098
                gtk_dialog_run(GTK_DIALOG(dialog));
 
1099
                gtk_widget_destroy(dialog);
 
1100
                return;
 
1101
        }
 
1102
 
 
1103
        for (i=0; i<state->stored_num_ous; i++) {
 
1104
                gtk_combo_box_remove_text(GTK_COMBO_BOX(state->entry_ou_list), 0);
 
1105
        }
 
1106
        for (i=0; i<num_ous && ous[i] != NULL; i++) {
 
1107
                gtk_combo_box_append_text(GTK_COMBO_BOX(state->entry_ou_list),
 
1108
                                          ous[i]);
 
1109
        }
 
1110
        NetApiBufferFree(ous);
 
1111
        state->stored_num_ous = num_ous;
 
1112
        gtk_combo_box_set_active(GTK_COMBO_BOX(state->entry_ou_list), num_ous-1);
 
1113
}
 
1114
 
 
1115
static void callback_do_change(GtkWidget *widget,
 
1116
                               gpointer data)
 
1117
{
 
1118
        GtkWidget *window;
 
1119
        GtkWidget *box1;
 
1120
        GtkWidget *bbox;
 
1121
        GtkWidget *button_workgroup;
 
1122
        GtkWidget *button_domain;
 
1123
        GtkWidget *button;
 
1124
        GtkWidget *label;
 
1125
        GtkWidget *frame_horz;
 
1126
        GtkWidget *vbox;
 
1127
        GtkWidget *entry;
 
1128
        GSList *group;
 
1129
 
 
1130
        struct join_state *state = (struct join_state *)data;
 
1131
 
 
1132
        debug("callback_do_change called\n");
 
1133
 
 
1134
#if 0
 
1135
        /* FIXME: add proper warnings for Samba as a DC */
 
1136
        if (state->server_role == 3) {
 
1137
                GtkWidget *dialog;
 
1138
                callback_do_freeauth(NULL, state);
 
1139
                dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
 
1140
                                                GTK_DIALOG_DESTROY_WITH_PARENT,
 
1141
                                                GTK_MESSAGE_ERROR,
 
1142
                                                GTK_BUTTONS_OK,
 
1143
                                                "Domain controller cannot be moved from one domain to another, they must first be demoted. Renaming this domain controller may cause it to become temporarily unavailable to users and computers. For information on renaming domain controllers, including alternate renaming methods, see Help and Support. To continue renaming this domain controller, click OK.");
 
1144
                gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
1145
                g_signal_connect_swapped(dialog, "response",
 
1146
                                         G_CALLBACK(gtk_widget_destroy),
 
1147
                                         dialog);
 
1148
 
 
1149
                gtk_widget_show(dialog);
 
1150
                return;
 
1151
        }
 
1152
#endif
 
1153
 
 
1154
        state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
 
1155
        state->button_get_ous = gtk_button_new_with_label("Scan for joinable OUs");
 
1156
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
1157
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
 
1158
 
 
1159
        gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
 
1160
        gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
 
1161
        gtk_widget_set_size_request(GTK_WIDGET(window), 480, 650);
 
1162
        gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
 
1163
        gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_main));
 
1164
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
 
1165
 
 
1166
        g_signal_connect(G_OBJECT(window), "delete_event",
 
1167
                         G_CALLBACK(callback_do_close_widget), NULL);
 
1168
 
 
1169
        gtk_container_set_border_width(GTK_CONTAINER(window), 10);
 
1170
 
 
1171
        box1 = gtk_vbox_new(FALSE, 0);
 
1172
        gtk_container_add(GTK_CONTAINER(window), box1);
 
1173
 
 
1174
        label = gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network ressources.");
 
1175
        gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 
1176
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
1177
        gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
 
1178
        gtk_widget_show(label);
 
1179
 
 
1180
        /* COMPUTER NAME */
 
1181
        label = gtk_label_new("Computer name:");
 
1182
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
1183
        gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
 
1184
        gtk_widget_show(label);
 
1185
 
 
1186
        state->label_full_computer_name = gtk_label_new(NULL);
 
1187
        {
 
1188
                entry = gtk_entry_new();
 
1189
                gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_NETBIOS_NAME_LEN);
 
1190
                g_signal_connect(G_OBJECT(entry), "changed",
 
1191
                                 G_CALLBACK(callback_enter_hostname_and_unlock),
 
1192
                                 (gpointer)state);
 
1193
                gtk_entry_set_text(GTK_ENTRY(entry), state->my_hostname);
 
1194
                gtk_editable_select_region(GTK_EDITABLE(entry),
 
1195
                                           0, GTK_ENTRY(entry)->text_length);
 
1196
 
 
1197
                gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
 
1198
                gtk_box_pack_start(GTK_BOX(box1), entry, TRUE, TRUE, 0);
 
1199
                gtk_widget_show(entry);
 
1200
        }
 
1201
 
 
1202
        /* FULL COMPUTER NAME */
 
1203
        label = gtk_label_new("Full computer name:");
 
1204
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
1205
        gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
 
1206
        gtk_widget_show(label);
 
1207
 
 
1208
        {
 
1209
                const gchar *entry_text;
 
1210
                char *str = NULL;
 
1211
                entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
 
1212
                if (state->name_type_initial == NetSetupDomainName) {
 
1213
                        if (asprintf(&str, "%s.%s", entry_text,
 
1214
                                 state->my_dnsdomain) == -1) {
 
1215
                                return;
 
1216
                        }
 
1217
                } else {
 
1218
                        if (asprintf(&str, "%s.", entry_text) == -1) {
 
1219
                                return;
 
1220
                        }
 
1221
                }
 
1222
                gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
 
1223
                                   str);
 
1224
                free(str);
 
1225
                gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
 
1226
                gtk_box_pack_start(GTK_BOX(box1),
 
1227
                                   state->label_full_computer_name, TRUE, TRUE, 0);
 
1228
                gtk_widget_show(state->label_full_computer_name);
 
1229
        }
 
1230
 
 
1231
        /* BOX */
 
1232
        frame_horz = gtk_frame_new ("Member Of");
 
1233
        gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
 
1234
 
 
1235
        vbox = gtk_vbox_new(FALSE, 0);
 
1236
        gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
 
1237
        gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
 
1238
 
 
1239
        /* TWO ENTRIES */
 
1240
        state->entry_workgroup = gtk_entry_new();
 
1241
        state->entry_domain = gtk_entry_new();
 
1242
 
 
1243
        /* DOMAIN */
 
1244
        button_domain = gtk_radio_button_new_with_label(NULL, "Domain");
 
1245
        if (state->name_type_initial == NetSetupDomainName) {
 
1246
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain), TRUE);
 
1247
        }
 
1248
        gtk_box_pack_start(GTK_BOX(vbox), button_domain, TRUE, TRUE, 0);
 
1249
        g_signal_connect(G_OBJECT(button_domain), "clicked",
 
1250
                         G_CALLBACK(callback_do_join_domain),
 
1251
                         (gpointer)state);
 
1252
 
 
1253
        {
 
1254
                gtk_entry_set_max_length(GTK_ENTRY(state->entry_domain), 50);
 
1255
                g_signal_connect(G_OBJECT(state->entry_domain), "changed",
 
1256
                                 G_CALLBACK(callback_enter_domain_and_unlock),
 
1257
                                 (gpointer)state);
 
1258
                g_signal_connect(G_OBJECT(state->entry_domain), "activate",
 
1259
                                 G_CALLBACK(callback_continue),
 
1260
                                 (gpointer)state);
 
1261
                if (state->name_type_initial == NetSetupDomainName) {
 
1262
                        gtk_entry_set_text(GTK_ENTRY(state->entry_domain),
 
1263
                                           state->name_buffer_initial);
 
1264
                        gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
 
1265
                        gtk_widget_set_sensitive(state->entry_domain, TRUE);
 
1266
                }
 
1267
                gtk_editable_set_editable(GTK_EDITABLE(state->entry_domain), TRUE);
 
1268
                gtk_box_pack_start(GTK_BOX(vbox), state->entry_domain, TRUE, TRUE, 0);
 
1269
                gtk_widget_show(state->entry_domain);
 
1270
        }
 
1271
        gtk_widget_show(button_domain);
 
1272
 
 
1273
        /* WORKGROUP */
 
1274
        group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain));
 
1275
        button_workgroup = gtk_radio_button_new_with_label(group, "Workgroup");
 
1276
        if (state->name_type_initial == NetSetupWorkgroupName) {
 
1277
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup), TRUE);
 
1278
        }
 
1279
        gtk_box_pack_start(GTK_BOX(vbox), button_workgroup, TRUE, TRUE, 0);
 
1280
        g_signal_connect(G_OBJECT(button_workgroup), "clicked",
 
1281
                         G_CALLBACK(callback_do_join_workgroup),
 
1282
                         (gpointer)state);
 
1283
        {
 
1284
                gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup),
 
1285
                                         MAX_NETBIOS_NAME_LEN);
 
1286
                g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
 
1287
                                 G_CALLBACK(callback_enter_workgroup_and_unlock),
 
1288
                                 (gpointer)state);
 
1289
                g_signal_connect(G_OBJECT(state->entry_workgroup), "activate",
 
1290
                                 G_CALLBACK(callback_continue),
 
1291
                                 (gpointer)state);
 
1292
 
 
1293
                if (state->name_type_initial == NetSetupWorkgroupName) {
 
1294
                        gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup),
 
1295
                                           state->name_buffer_initial);
 
1296
                        gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
 
1297
                        gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
 
1298
                }
 
1299
                gtk_box_pack_start(GTK_BOX(vbox), state->entry_workgroup, TRUE, TRUE, 0);
 
1300
                gtk_widget_show(state->entry_workgroup);
 
1301
        }
 
1302
        gtk_widget_show(button_workgroup);
 
1303
 
 
1304
        /* Advanced Options */
 
1305
        frame_horz = gtk_frame_new("Advanced Options");
 
1306
        gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
 
1307
 
 
1308
        vbox = gtk_vbox_new(FALSE, 0);
 
1309
        gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
 
1310
        gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
 
1311
 
 
1312
        /* OUs */
 
1313
        gtk_container_add(GTK_CONTAINER(vbox), state->button_get_ous);
 
1314
        gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
 
1315
        g_signal_connect(G_OBJECT(state->button_get_ous), "clicked",
 
1316
                         G_CALLBACK(callback_do_getous),
 
1317
                         (gpointer)state);
 
1318
 
 
1319
        state->entry_ou_list = gtk_combo_box_entry_new_text();
 
1320
        gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
 
1321
        if (state->name_type_initial == NetSetupWorkgroupName) {
 
1322
                gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
 
1323
                gtk_widget_set_sensitive(state->button_get_ous, FALSE);
 
1324
        }
 
1325
        gtk_box_pack_start(GTK_BOX(vbox), state->entry_ou_list, TRUE, TRUE, 0);
 
1326
        gtk_widget_show(state->entry_ou_list);
 
1327
 
 
1328
        {
 
1329
                state->label_winbind = gtk_check_button_new_with_label("Modify winbind configuration");
 
1330
                gtk_box_pack_start(GTK_BOX(vbox), state->label_winbind, TRUE, TRUE, 0);
 
1331
                gtk_widget_set_sensitive(state->label_winbind, FALSE);
 
1332
        }
 
1333
 
 
1334
 
 
1335
        /* BUTTONS */
 
1336
        bbox = gtk_hbutton_box_new();
 
1337
        gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
 
1338
        gtk_container_add(GTK_CONTAINER(box1), bbox);
 
1339
        gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
 
1340
        gtk_box_set_spacing(GTK_BOX(bbox), 10);
 
1341
 
 
1342
        state->window_do_change = window;
 
1343
        gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 
1344
        gtk_container_add(GTK_CONTAINER(bbox), state->button_ok);
 
1345
        g_signal_connect(G_OBJECT(state->button_ok), "clicked",
 
1346
                         G_CALLBACK(callback_do_join),
 
1347
                         (gpointer)state);
 
1348
 
 
1349
        button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
 
1350
        gtk_container_add(GTK_CONTAINER(bbox), button);
 
1351
        g_signal_connect(G_OBJECT(button), "clicked",
 
1352
                         G_CALLBACK(callback_do_freeauth_and_close),
 
1353
                         (gpointer)state);
 
1354
 
 
1355
        gtk_widget_show_all(window);
 
1356
}
 
1357
 
 
1358
static void callback_do_about(GtkWidget *widget,
 
1359
                             gpointer data)
 
1360
{
 
1361
        GdkPixbuf *logo;
 
1362
        GError    *error = NULL;
 
1363
        GtkWidget *about;
 
1364
 
 
1365
        struct join_state *state = (struct join_state *)data;
 
1366
 
 
1367
        debug("callback_do_about called\n");
 
1368
 
 
1369
        logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
 
1370
                                        &error);
 
1371
        if (logo == NULL) {
 
1372
                g_print("failed to load logo from %s: %s\n",
 
1373
                        SAMBA_IMAGE_PATH, error->message);
 
1374
        }
 
1375
 
 
1376
        about = gtk_about_dialog_new();
 
1377
        gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about), "Samba");
 
1378
        gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), "3.2.0pre3");
 
1379
        gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about),
 
1380
                "Copyright Andrew Tridgell and the Samba Team 1992-2008\n"
 
1381
                "Copyright Günther Deschner 2007-2008");
 
1382
        gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about), "GPLv3");
 
1383
        gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
 
1384
        gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
 
1385
        if (logo) {
 
1386
                gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), logo);
 
1387
        }
 
1388
        gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about), "Samba gtk domain join utility");
 
1389
        gtk_window_set_modal(GTK_WINDOW(about), TRUE);
 
1390
        gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(state->window_main));
 
1391
        g_signal_connect_swapped(about, "response",
 
1392
                                 G_CALLBACK(gtk_widget_destroy),
 
1393
                                 about);
 
1394
 
 
1395
        gtk_widget_show(about);
 
1396
}
 
1397
 
 
1398
static int draw_main_window(struct join_state *state)
 
1399
{
 
1400
        GtkWidget *window;
 
1401
        GtkWidget *button;
 
1402
        GtkWidget *label;
 
1403
        GtkWidget *main_vbox;
 
1404
        GtkWidget *vbox;
 
1405
        GtkWidget *hbox;
 
1406
        GtkWidget *bbox;
 
1407
        GtkWidget *image;
 
1408
        GtkWidget *table;
 
1409
        GtkWidget *entry;
 
1410
        GdkPixbuf *icon;
 
1411
        GError    *error = NULL;
 
1412
 
 
1413
        icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
 
1414
                                        &error);
 
1415
        if (icon == NULL) {
 
1416
                g_print("failed to load icon from %s : %s\n",
 
1417
                        SAMBA_ICON_PATH, error->message);
 
1418
        }
 
1419
 
 
1420
#if 1
 
1421
        image = gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL);
 
1422
#else
 
1423
        image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
 
1424
#endif
 
1425
        if (image == NULL) {
 
1426
                g_print("failed to load logo from %s : %s\n",
 
1427
                        SAMBA_IMAGE_PATH_SMALL, error->message);
 
1428
        }
 
1429
 
 
1430
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
1431
        state->window_main = window;
 
1432
 
 
1433
        gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
 
1434
        gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
 
1435
        gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
 
1436
        gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
 
1437
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
 
1438
 
 
1439
        g_signal_connect(G_OBJECT(window), "delete_event",
 
1440
                         G_CALLBACK(callback_delete_event), NULL);
 
1441
 
 
1442
        gtk_container_set_border_width(GTK_CONTAINER(window), 10);
 
1443
 
 
1444
        main_vbox = gtk_vbox_new(FALSE, 10);
 
1445
        gtk_container_add(GTK_CONTAINER(window), main_vbox);
 
1446
 
 
1447
#if 0
 
1448
        gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10);
 
1449
        gtk_widget_show(image);
 
1450
#endif
 
1451
        /* Hbox */
 
1452
        hbox = gtk_hbox_new(FALSE, 10);
 
1453
        gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
 
1454
 
 
1455
        {
 
1456
/*              gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
 
1457
/*              gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
 
1458
                gtk_widget_set_size_request(GTK_WIDGET(image), 150, 40);
 
1459
                gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
 
1460
                gtk_widget_show(image);
 
1461
 
 
1462
                /* Label */
 
1463
                label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
 
1464
/*              gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
 
1465
                gtk_widget_set_size_request(GTK_WIDGET(label), 400, 40);
 
1466
                gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 
1467
                gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
 
1468
                gtk_widget_show(label);
 
1469
        }
 
1470
 
 
1471
        gtk_widget_show(hbox);
 
1472
 
 
1473
        vbox = gtk_vbox_new(FALSE, 0);
 
1474
        gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
 
1475
        gtk_container_add(GTK_CONTAINER(main_vbox), vbox);
 
1476
 
 
1477
        /* Table */
 
1478
        table = gtk_table_new(6, 3, TRUE);
 
1479
        gtk_table_set_row_spacings(GTK_TABLE(table), 5);
 
1480
        gtk_table_set_col_spacings(GTK_TABLE(table), 5);
 
1481
        gtk_container_add(GTK_CONTAINER(vbox), table);
 
1482
 
 
1483
        {
 
1484
                /* Label */
 
1485
                label = gtk_label_new("Computer description:");
 
1486
                gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
1487
                gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
 
1488
                gtk_widget_show(label);
 
1489
 
 
1490
                state->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
 
1491
 
 
1492
                /* Entry */
 
1493
                entry = gtk_entry_new();
 
1494
                gtk_entry_set_max_length(GTK_ENTRY(entry), 256);
 
1495
 
 
1496
                if (!state->target_hostname && state->uid != 0) {
 
1497
                        gtk_widget_set_sensitive(GTK_WIDGET(entry), FALSE);
 
1498
                }
 
1499
                g_signal_connect(G_OBJECT(entry), "changed",
 
1500
                                 G_CALLBACK(callback_enter_computer_description_and_unlock),
 
1501
                                 state);
 
1502
                g_signal_connect(G_OBJECT(entry), "activate",
 
1503
                                 G_CALLBACK(callback_apply_continue),
 
1504
                                 (gpointer)state);
 
1505
 
 
1506
                gtk_entry_set_text(GTK_ENTRY(entry), (char *)state->comment);
 
1507
                gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
 
1508
                gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 3, 0, 1);
 
1509
                gtk_widget_show(entry);
 
1510
        }
 
1511
 
 
1512
        /* Label */
 
1513
        label = gtk_label_new("For example: \"Samba \%v\".");
 
1514
        gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 
1515
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
1516
        gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 1, 2);
 
1517
        gtk_widget_show(label);
 
1518
 
 
1519
        /* Label */
 
1520
        label = gtk_label_new("Full computer name:");
 
1521
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
1522
        gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
 
1523
        gtk_widget_show(label);
 
1524
 
 
1525
        {
 
1526
                /* Label */
 
1527
                char *str = NULL;
 
1528
                if (state->name_type_initial == NetSetupDomainName) {
 
1529
                        if (asprintf(&str, "%s.%s", state->my_hostname,
 
1530
                                 state->my_dnsdomain) == -1) {
 
1531
                                return -1;
 
1532
                        }
 
1533
                } else {
 
1534
                        if (asprintf(&str, "%s.", state->my_hostname) == -1) {
 
1535
                                return -1;
 
1536
                        }
 
1537
                }
 
1538
 
 
1539
                label = gtk_label_new(str);
 
1540
                SAFE_FREE(str);
 
1541
                gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
1542
                gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 2, 3);
 
1543
                gtk_widget_show(label);
 
1544
        }
 
1545
 
 
1546
        /* Label */
 
1547
        if (state->name_type_initial == NetSetupDomainName) {
 
1548
                label = gtk_label_new("Domain:");
 
1549
        } else {
 
1550
                label = gtk_label_new("Workgroup:");
 
1551
        }
 
1552
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
1553
        gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
 
1554
        gtk_widget_show(label);
 
1555
        state->label_current_name_type = label;
 
1556
 
 
1557
        /* Label */
 
1558
        label = gtk_label_new(state->name_buffer_initial);
 
1559
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 
1560
        gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 3, 4);
 
1561
        gtk_widget_show(label);
 
1562
        state->label_current_name_buffer = label;
 
1563
 
 
1564
        {
 
1565
                hbox = gtk_hbox_new(FALSE, 0);
 
1566
                gtk_container_add(GTK_CONTAINER(vbox), hbox);
 
1567
                label = gtk_label_new("To rename this computer or join a domain, click Change.");
 
1568
                gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
 
1569
 
 
1570
 
 
1571
        }
 
1572
 
 
1573
        /* bbox */
 
1574
        bbox = gtk_hbutton_box_new();
 
1575
        gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
 
1576
        gtk_container_add(GTK_CONTAINER(hbox), bbox);
 
1577
        gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
 
1578
        gtk_box_set_spacing(GTK_BOX(bbox), 10);
 
1579
 
 
1580
        button = gtk_button_new_with_mnemonic("Ch_ange");
 
1581
        g_signal_connect(G_OBJECT(button), "clicked",
 
1582
                         G_CALLBACK(callback_do_change),
 
1583
                         (gpointer)state);
 
1584
        gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
 
1585
        if (!state->target_hostname && state->uid != 0) {
 
1586
                gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
 
1587
        }
 
1588
        gtk_widget_show(button);
 
1589
 
 
1590
        /* Label (hidden) */
 
1591
        state->label_reboot = gtk_label_new(NULL);
 
1592
        gtk_label_set_line_wrap(GTK_LABEL(state->label_reboot), TRUE);
 
1593
        gtk_misc_set_alignment(GTK_MISC(state->label_reboot), 0, 0);
 
1594
        gtk_box_pack_start(GTK_BOX(vbox), state->label_reboot, TRUE, TRUE, 0);
 
1595
        if (!state->target_hostname && state->uid != 0) {
 
1596
                gtk_label_set_text(GTK_LABEL(state->label_reboot),
 
1597
                           "You cannot change computer description as you're not running with root permissions");
 
1598
        }
 
1599
 
 
1600
        gtk_widget_show(state->label_reboot);
 
1601
 
 
1602
#if 0
 
1603
        gtk_box_pack_start(GTK_BOX(vbox),
 
1604
           create_bbox(window, TRUE, NULL, 10, 85, 20, GTK_BUTTONBOX_END),
 
1605
                      TRUE, TRUE, 5);
 
1606
#endif
 
1607
        {
 
1608
 
 
1609
                GtkWidget *frame;
 
1610
                GtkWidget *bbox2;
 
1611
                GtkWidget *button2;
 
1612
 
 
1613
                frame = gtk_frame_new(NULL);
 
1614
                bbox2 = gtk_hbutton_box_new();
 
1615
 
 
1616
                gtk_container_set_border_width(GTK_CONTAINER(bbox2), 5);
 
1617
                gtk_container_add(GTK_CONTAINER(frame), bbox2);
 
1618
 
 
1619
                /* Set the appearance of the Button Box */
 
1620
                gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2), GTK_BUTTONBOX_END);
 
1621
                gtk_box_set_spacing(GTK_BOX(bbox2), 10);
 
1622
                /*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
 
1623
 
 
1624
                button2 = gtk_button_new_from_stock(GTK_STOCK_OK);
 
1625
                gtk_container_add(GTK_CONTAINER(bbox2), button2);
 
1626
                g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(callback_do_exit), state);
 
1627
 
 
1628
                button2 = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
 
1629
                gtk_container_add(GTK_CONTAINER(bbox2), button2);
 
1630
                g_signal_connect(G_OBJECT(button2), "clicked",
 
1631
                                 G_CALLBACK(callback_delete_event),
 
1632
                                 window);
 
1633
 
 
1634
                gtk_container_add(GTK_CONTAINER(bbox2), state->button_apply);
 
1635
                g_signal_connect(G_OBJECT(state->button_apply), "clicked",
 
1636
                                 G_CALLBACK(callback_apply_description_change),
 
1637
                                 state);
 
1638
                gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
 
1639
 
 
1640
                button2 = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
 
1641
                gtk_container_add(GTK_CONTAINER(bbox2), button2);
 
1642
                g_signal_connect(G_OBJECT(button2), "clicked",
 
1643
                                 G_CALLBACK(callback_do_about),
 
1644
                                 state);
 
1645
#if 0
 
1646
                button2 = gtk_button_new_from_stock(GTK_STOCK_HELP);
 
1647
                gtk_container_add(GTK_CONTAINER(bbox2), button2);
 
1648
                g_signal_connect(G_OBJECT(button2), "clicked",
 
1649
                                 G_CALLBACK(callback_do_about),
 
1650
                                 window);
 
1651
#endif
 
1652
                gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
 
1653
        }
 
1654
 
 
1655
        gtk_widget_show_all(window);
 
1656
 
 
1657
        return 0;
 
1658
}
 
1659
 
 
1660
static int init_join_state(struct join_state **state)
 
1661
{
 
1662
        struct join_state *s;
 
1663
 
 
1664
        s = (struct join_state *)malloc(sizeof(struct join_state));
 
1665
        if (!s) {
 
1666
                return -1;
 
1667
        }
 
1668
 
 
1669
        memset(s, '\0', sizeof(struct join_state));
 
1670
 
 
1671
        *state = s;
 
1672
 
 
1673
        return 0;
 
1674
}
 
1675
 
 
1676
static NET_API_STATUS get_server_properties(struct join_state *state)
 
1677
{
 
1678
        struct SERVER_INFO_101 *info101 = NULL;
 
1679
        struct SERVER_INFO_1005 *info1005 = NULL;
 
1680
        NET_API_STATUS status;
 
1681
 
 
1682
        status = NetServerGetInfo(state->target_hostname,
 
1683
                                  101,
 
1684
                                  (uint8_t **)&info101);
 
1685
        if (status == 0) {
 
1686
                state->comment = strdup(info101->sv101_comment);
 
1687
                if (!state->comment) {
 
1688
                        return -1;
 
1689
                }
 
1690
                SAFE_FREE(state->my_hostname);
 
1691
                state->my_hostname = strdup(info101->sv101_name);
 
1692
                if (!state->my_hostname) {
 
1693
                        return -1;
 
1694
                }
 
1695
                NetApiBufferFree(info101);
 
1696
                return NET_API_STATUS_SUCCESS;
 
1697
        }
 
1698
 
 
1699
        switch (status) {
 
1700
                case 124: /* WERR_UNKNOWN_LEVEL */
 
1701
                case 50: /* WERR_NOT_SUPPORTED */
 
1702
                        break;
 
1703
                default:
 
1704
                        goto failed;
 
1705
        }
 
1706
 
 
1707
        status = NetServerGetInfo(state->target_hostname,
 
1708
                                  1005,
 
1709
                                  (uint8_t **)&info1005);
 
1710
        if (status == 0) {
 
1711
                state->comment = strdup(info1005->sv1005_comment);
 
1712
                if (!state->comment) {
 
1713
                        return -1;
 
1714
                }
 
1715
                NetApiBufferFree(info1005);
 
1716
                return NET_API_STATUS_SUCCESS;
 
1717
        }
 
1718
 
 
1719
 failed:
 
1720
        printf("NetServerGetInfo failed with: %s\n",
 
1721
                libnetapi_get_error_string(state->ctx, status));
 
1722
 
 
1723
        return status;
 
1724
}
 
1725
 
 
1726
static int initialize_join_state(struct join_state *state,
 
1727
                                 const char *debug_level,
 
1728
                                 const char *target_hostname,
 
1729
                                 const char *target_username)
 
1730
{
 
1731
        struct libnetapi_ctx *ctx = NULL;
 
1732
        NET_API_STATUS status = 0;
 
1733
 
 
1734
        status = libnetapi_init(&ctx);
 
1735
        if (status) {
 
1736
                return status;
 
1737
        }
 
1738
 
 
1739
        if (debug_level) {
 
1740
                libnetapi_set_debuglevel(ctx, debug_level);
 
1741
        }
 
1742
 
 
1743
        if (target_hostname) {
 
1744
                state->target_hostname = strdup(target_hostname);
 
1745
                if (!state->target_hostname) {
 
1746
                        return -1;
 
1747
                }
 
1748
        }
 
1749
 
 
1750
        if (target_username) {
 
1751
                char *puser = strdup(target_username);
 
1752
                char *p = NULL;
 
1753
 
 
1754
                if ((p = strchr(puser,'%'))) {
 
1755
                        size_t len;
 
1756
                        *p = 0;
 
1757
                        libnetapi_set_username(ctx, puser);
 
1758
                        libnetapi_set_password(ctx, p+1);
 
1759
                        len = strlen(p+1);
 
1760
                        memset(strchr(target_username,'%')+1,'X',len);
 
1761
                } else {
 
1762
                        libnetapi_set_username(ctx, puser);
 
1763
                }
 
1764
                free(puser);
 
1765
        }
 
1766
 
 
1767
        {
 
1768
                char my_hostname[HOST_NAME_MAX];
 
1769
                const char *p = NULL;
 
1770
                struct hostent *hp = NULL;
 
1771
 
 
1772
                if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
 
1773
                        return -1;
 
1774
                }
 
1775
 
 
1776
                p = strchr(my_hostname, '.');
 
1777
                if (p) {
 
1778
                        my_hostname[strlen(my_hostname)-strlen(p)] = '\0';
 
1779
                }
 
1780
                state->my_hostname = strdup(my_hostname);
 
1781
                if (!state->my_hostname) {
 
1782
                        return -1;
 
1783
                }
 
1784
                debug("state->my_hostname: %s\n", state->my_hostname);
 
1785
 
 
1786
                hp = gethostbyname(my_hostname);
 
1787
                if (!hp || !hp->h_name || !*hp->h_name) {
 
1788
                        return -1;
 
1789
                }
 
1790
 
 
1791
                state->my_fqdn = strdup(hp->h_name);
 
1792
                if (!state->my_fqdn) {
 
1793
                        return -1;
 
1794
                }
 
1795
                debug("state->my_fqdn: %s\n", state->my_fqdn);
 
1796
 
 
1797
                p = strchr(state->my_fqdn, '.');
 
1798
                if (p) {
 
1799
                        p++;
 
1800
                        state->my_dnsdomain = strdup(p);
 
1801
                } else {
 
1802
                        state->my_dnsdomain = strdup("");
 
1803
                }
 
1804
                if (!state->my_dnsdomain) {
 
1805
                        return -1;
 
1806
                }
 
1807
                debug("state->my_dnsdomain: %s\n", state->my_dnsdomain);
 
1808
        }
 
1809
 
 
1810
        {
 
1811
                const char *buffer = NULL;
 
1812
                uint16_t type = 0;
 
1813
                status = NetGetJoinInformation(state->target_hostname,
 
1814
                                               &buffer,
 
1815
                                               &type);
 
1816
                if (status != 0) {
 
1817
                        printf("NetGetJoinInformation failed with: %s\n",
 
1818
                                libnetapi_get_error_string(state->ctx, status));
 
1819
                        return status;
 
1820
                }
 
1821
                debug("NetGetJoinInformation gave: %s and %d\n", buffer, type);
 
1822
                state->name_buffer_initial = strdup(buffer);
 
1823
                if (!state->name_buffer_initial) {
 
1824
                        return -1;
 
1825
                }
 
1826
                state->name_type_initial = type;
 
1827
                NetApiBufferFree((void *)buffer);
 
1828
        }
 
1829
 
 
1830
        status = get_server_properties(state);
 
1831
        if (status != 0) {
 
1832
                return -1;
 
1833
        }
 
1834
 
 
1835
        state->uid = geteuid();
 
1836
 
 
1837
        state->ctx = ctx;
 
1838
 
 
1839
        return 0;
 
1840
}
 
1841
 
 
1842
int main(int argc, char **argv)
 
1843
{
 
1844
        GOptionContext *context = NULL;
 
1845
        static const char *debug_level = NULL;
 
1846
        static const char *target_hostname = NULL;
 
1847
        static const char *target_username = NULL;
 
1848
        struct join_state *state = NULL;
 
1849
        GError *error = NULL;
 
1850
        int ret = 0;
 
1851
 
 
1852
        static GOptionEntry entries[] = {
 
1853
                { "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
 
1854
                { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
 
1855
                { "target", 'S', 0, G_OPTION_ARG_STRING, &target_hostname, "Target hostname", 0 },
 
1856
                { "username", 'U', 0, G_OPTION_ARG_STRING, &target_username, "Target hostname", 0 },
 
1857
                { NULL }
 
1858
        };
 
1859
 
 
1860
        context = g_option_context_new("- Samba domain join utility");
 
1861
        g_option_context_add_main_entries(context, entries, NULL);
 
1862
/*      g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
 
1863
        g_option_context_add_group(context, gtk_get_option_group(TRUE));
 
1864
        g_option_context_parse(context, &argc, &argv, &error);
 
1865
 
 
1866
        gtk_init(&argc, &argv);
 
1867
        g_set_application_name("Samba");
 
1868
 
 
1869
        ret = init_join_state(&state);
 
1870
        if (ret) {
 
1871
                return ret;
 
1872
        }
 
1873
 
 
1874
        ret = initialize_join_state(state, debug_level,
 
1875
                                    target_hostname,
 
1876
                                    target_username);
 
1877
        if (ret) {
 
1878
                return ret;
 
1879
        }
 
1880
 
 
1881
        draw_main_window(state);
 
1882
 
 
1883
        gtk_main();
 
1884
 
 
1885
        do_cleanup(state);
 
1886
 
 
1887
        return 0;
 
1888
}