~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to examples/libsmbclient/tree.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/Netbios implementation.
 
3
   Version 2.0
 
4
   SMB client GTK+ tree-based application
 
5
   Copyright (C) Andrew Tridgell 1998
 
6
   Copyright (C) Richard Sharpe 2001
 
7
   Copyright (C) John Terpstra 2001
 
8
   
 
9
   This program is free software; you can redistribute it and/or modify
 
10
   it under the terms of the GNU General Public License as published by
 
11
   the Free Software Foundation; either version 3 of the License, or
 
12
   (at your option) any later version.
 
13
   
 
14
   This program is distributed in the hope that it will be useful,
 
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
   GNU General Public License for more details.
 
18
   
 
19
   You should have received a copy of the GNU General Public License
 
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
21
*/
 
22
 
 
23
/* example-gtk+ application, ripped off from the gtk+ tree.c sample */
 
24
 
 
25
#include <stdio.h>
 
26
#include <errno.h>
 
27
#include <string.h>
 
28
#include <stdlib.h>
 
29
#include <gtk/gtk.h>
 
30
#include "libsmbclient.h"
 
31
 
 
32
static GtkWidget *clist;
 
33
 
 
34
struct tree_data {
 
35
 
 
36
  guint32 type;    /* Type of tree item, an SMBC_TYPE */
 
37
  char name[256];  /* May need to change this later   */
 
38
 
 
39
};
 
40
 
 
41
void error_message(gchar *message) {
 
42
 
 
43
  GtkWidget *dialog, *label, *okay_button;
 
44
     
 
45
  /* Create the widgets */
 
46
     
 
47
  dialog = gtk_dialog_new();
 
48
  gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 
49
  label = gtk_label_new (message);
 
50
  okay_button = gtk_button_new_with_label("Okay");
 
51
     
 
52
  /* Ensure that the dialog box is destroyed when the user clicks ok. */
 
53
     
 
54
  gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked",
 
55
                             GTK_SIGNAL_FUNC (gtk_widget_destroy), 
 
56
                             GTK_OBJECT(dialog));
 
57
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
 
58
                     okay_button);
 
59
 
 
60
  /* Add the label, and show everything we've added to the dialog. */
 
61
 
 
62
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
 
63
                     label);
 
64
  gtk_widget_show_all (dialog);
 
65
}
 
66
 
 
67
/*
 
68
 * We are given a widget, and we want to retrieve its URL so we 
 
69
 * can do a directory listing.
 
70
 *
 
71
 * We walk back up the tree, picking up pieces until we hit a server or
 
72
 * workgroup type and return a path from there
 
73
 */
 
74
 
 
75
static char path_string[1024];
 
76
 
 
77
char *get_path(GtkWidget *item)
 
78
{
 
79
  GtkWidget *p = item;
 
80
  struct tree_data *pd;
 
81
  char *comps[1024];  /* We keep pointers to the components here */
 
82
  int i = 0, j, level,type;
 
83
 
 
84
  /* Walk back up the tree, getting the private data */
 
85
 
 
86
  level = GTK_TREE(item->parent)->level;
 
87
 
 
88
  /* Pick up this item's component info */
 
89
 
 
90
  pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(item));
 
91
 
 
92
  comps[i++] = pd->name;
 
93
  type = pd->type;
 
94
 
 
95
  while (level > 0 && type != SMBC_SERVER && type != SMBC_WORKGROUP) {
 
96
 
 
97
    /* Find the parent and extract the data etc ... */
 
98
 
 
99
    p = GTK_WIDGET(p->parent);    
 
100
    p = GTK_WIDGET(GTK_TREE(p)->tree_owner);
 
101
 
 
102
    pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(p));
 
103
 
 
104
    level = GTK_TREE(item->parent)->level;
 
105
 
 
106
    comps[i++] = pd->name;
 
107
    type = pd->type;
 
108
 
 
109
  }
 
110
 
 
111
  /* 
 
112
   * Got a list of comps now, should check that we did not hit a workgroup
 
113
   * when we got other things as well ... Later
 
114
   *
 
115
   * Now, build the path
 
116
   */
 
117
 
 
118
  snprintf(path_string, sizeof(path_string), "smb:/");
 
119
 
 
120
  for (j = i - 1; j >= 0; j--) {
 
121
 
 
122
    strncat(path_string, "/", sizeof(path_string) - strlen(path_string));
 
123
    strncat(path_string, comps[j], sizeof(path_string) - strlen(path_string));
 
124
 
 
125
  }
 
126
  
 
127
  fprintf(stdout, "Path string = %s\n", path_string);
 
128
 
 
129
  return path_string;
 
130
 
 
131
}
 
132
 
 
133
struct tree_data *make_tree_data(guint32 type, const char *name)
 
134
{
 
135
  struct tree_data *p = (struct tree_data *)malloc(sizeof(struct tree_data));
 
136
 
 
137
  if (p) {
 
138
 
 
139
    p->type = type;
 
140
    strncpy(p->name, name, sizeof(p->name));
 
141
 
 
142
  }
 
143
 
 
144
  return p;
 
145
 
 
146
}
 
147
 
 
148
/* Note that this is called every time the user clicks on an item,
 
149
   whether it is already selected or not. */
 
150
static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
 
151
                             GtkWidget *subtree)
 
152
{
 
153
  gint dh, err, dirlen;
 
154
  char dirbuf[512];
 
155
  struct smbc_dirent *dirp;
 
156
  struct stat st1;
 
157
  char path[1024], path1[1024];
 
158
 
 
159
  g_print ("select_child called for root tree %p, subtree %p, child %p\n",
 
160
           root_tree, subtree, child);
 
161
 
 
162
  /* Now, figure out what it is, and display it in the clist ... */
 
163
 
 
164
  gtk_clist_clear(GTK_CLIST(clist));  /* Clear the CLIST */
 
165
 
 
166
  /* Now, get the private data for the subtree */
 
167
 
 
168
  strncpy(path, get_path(child), 1024);
 
169
 
 
170
  if ((dh = smbc_opendir(path)) < 0) { /* Handle error */
 
171
 
 
172
    g_print("cb_select_child: Could not open dir %s, %s\n", path,
 
173
            strerror(errno));
 
174
 
 
175
    gtk_main_quit();
 
176
 
 
177
    return;
 
178
 
 
179
  }
 
180
 
 
181
  while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf,
 
182
                              sizeof(dirbuf))) != 0) {
 
183
 
 
184
    if (err < 0) {
 
185
 
 
186
      g_print("cb_select_child: Could not read dir %s, %s\n", path,
 
187
              strerror(errno));
 
188
 
 
189
      gtk_main_quit();
 
190
 
 
191
      return;
 
192
 
 
193
    }
 
194
 
 
195
    dirp = (struct smbc_dirent *)dirbuf;
 
196
 
 
197
    while (err > 0) {
 
198
      gchar col1[128], col2[128], col3[128], col4[128];
 
199
      gchar *rowdata[4] = {col1, col2, col3, col4};
 
200
 
 
201
      dirlen = dirp->dirlen;
 
202
 
 
203
      /* Format each of the items ... */
 
204
 
 
205
      strncpy(col1, dirp->name, 128);
 
206
 
 
207
      col2[0] = col3[0] = col4[0] = (char)0;
 
208
 
 
209
      switch (dirp->smbc_type) {
 
210
 
 
211
      case SMBC_WORKGROUP:
 
212
 
 
213
        break;
 
214
 
 
215
      case SMBC_SERVER:
 
216
 
 
217
        strncpy(col2, (dirp->comment?dirp->comment:""), 128);
 
218
 
 
219
        break;
 
220
 
 
221
      case SMBC_FILE_SHARE:
 
222
 
 
223
        strncpy(col2, (dirp->comment?dirp->comment:""), 128);
 
224
 
 
225
        break;
 
226
 
 
227
      case SMBC_PRINTER_SHARE:
 
228
 
 
229
        strncpy(col2, (dirp->comment?dirp->comment:""), 128);
 
230
        break;
 
231
 
 
232
      case SMBC_COMMS_SHARE:
 
233
 
 
234
        break;
 
235
 
 
236
      case SMBC_IPC_SHARE:
 
237
 
 
238
        break;
 
239
 
 
240
      case SMBC_DIR:
 
241
      case SMBC_FILE:
 
242
 
 
243
        /* Get stats on the file/dir and see what we have */
 
244
 
 
245
        if ((strcmp(dirp->name, ".") != 0) &&
 
246
            (strcmp(dirp->name, "..") != 0)) {
 
247
 
 
248
          strncpy(path1, path, sizeof(path1));
 
249
          strncat(path1, "/", sizeof(path) - strlen(path));
 
250
          strncat(path1, dirp->name, sizeof(path) - strlen(path));
 
251
 
 
252
          if (smbc_stat(path1, &st1) < 0) {
 
253
            
 
254
            if (errno != EBUSY) {
 
255
              
 
256
              g_print("cb_select_child: Could not stat file %s, %s\n", path1, 
 
257
                      strerror(errno));
 
258
            
 
259
              gtk_main_quit();
 
260
 
 
261
              return;
 
262
 
 
263
            }
 
264
            else {
 
265
 
 
266
              strncpy(col2, "Device or resource busy", sizeof(col2));
 
267
 
 
268
            }
 
269
          }
 
270
          else {
 
271
            /* Now format each of the relevant things ... */
 
272
 
 
273
            snprintf(col2, sizeof(col2), "%c%c%c%c%c%c%c%c%c(%0X)",
 
274
                     (st1.st_mode&S_IRUSR?'r':'-'),
 
275
                     (st1.st_mode&S_IWUSR?'w':'-'),
 
276
                     (st1.st_mode&S_IXUSR?'x':'-'),
 
277
                     (st1.st_mode&S_IRGRP?'r':'-'),
 
278
                     (st1.st_mode&S_IWGRP?'w':'-'),
 
279
                     (st1.st_mode&S_IXGRP?'x':'-'),
 
280
                     (st1.st_mode&S_IROTH?'r':'-'),
 
281
                     (st1.st_mode&S_IWOTH?'w':'-'),
 
282
                     (st1.st_mode&S_IXOTH?'x':'-'),
 
283
                     st1.st_mode); 
 
284
            snprintf(col3, sizeof(col3), "%u", st1.st_size);
 
285
            snprintf(col4, sizeof(col4), "%s", ctime(&st1.st_mtime));
 
286
          }
 
287
        }
 
288
 
 
289
        break;
 
290
 
 
291
      default:
 
292
 
 
293
        break;
 
294
      }
 
295
 
 
296
      gtk_clist_append(GTK_CLIST(clist), rowdata);
 
297
 
 
298
      dirp = (struct smbc_dirent *) ((char *) dirp + dirlen);
 
299
      err -= dirlen;
 
300
 
 
301
    }
 
302
 
 
303
  }
 
304
 
 
305
}
 
306
 
 
307
/* Note that this is never called */
 
308
static void cb_unselect_child( GtkWidget *root_tree,
 
309
                               GtkWidget *child,
 
310
                               GtkWidget *subtree )
 
311
{
 
312
  g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
 
313
           root_tree, subtree, child);
 
314
}
 
315
 
 
316
/* for all the GtkItem:: and GtkTreeItem:: signals */
 
317
static void cb_itemsignal( GtkWidget *item,
 
318
                           gchar     *signame )
 
319
{
 
320
  GtkWidget *real_tree, *aitem, *subtree;
 
321
  gchar *name;
 
322
  GtkLabel *label;
 
323
  gint dh, err, dirlen, level;
 
324
  char dirbuf[512];
 
325
  struct smbc_dirent *dirp;
 
326
  
 
327
  label = GTK_LABEL (GTK_BIN (item)->child);
 
328
  /* Get the text of the label */
 
329
  gtk_label_get (label, &name);
 
330
 
 
331
  level = GTK_TREE(item->parent)->level;
 
332
 
 
333
  /* Get the level of the tree which the item is in */
 
334
  g_print ("%s called for item %s->%p, level %d\n", signame, name,
 
335
           item, GTK_TREE (item->parent)->level);
 
336
 
 
337
  real_tree = GTK_TREE_ITEM_SUBTREE(item);  /* Get the subtree */
 
338
 
 
339
  if (strncmp(signame, "expand", 6) == 0) { /* Expand called */
 
340
    char server[128];
 
341
 
 
342
    if ((dh = smbc_opendir(get_path(item))) < 0) { /* Handle error */
 
343
      gchar errmsg[256];
 
344
 
 
345
      g_print("cb_itemsignal: Could not open dir %s, %s\n", get_path(item), 
 
346
              strerror(errno));
 
347
 
 
348
      snprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not open dir %s, %s\n", get_path(item), strerror(errno));
 
349
 
 
350
      error_message(errmsg);
 
351
 
 
352
      /*      gtk_main_quit();*/
 
353
 
 
354
      return;
 
355
 
 
356
    }
 
357
 
 
358
    while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 
 
359
                                sizeof(dirbuf))) != 0) {
 
360
 
 
361
      if (err < 0) { /* An error, report it */
 
362
        gchar errmsg[256];
 
363
 
 
364
        g_print("cb_itemsignal: Could not read dir smbc://, %s\n",
 
365
                strerror(errno));
 
366
 
 
367
        snprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not read dir smbc://, %s\n", strerror(errno));
 
368
 
 
369
        error_message(errmsg);
 
370
 
 
371
        /*      gtk_main_quit();*/
 
372
 
 
373
        return;
 
374
 
 
375
      }
 
376
 
 
377
      dirp = (struct smbc_dirent *)dirbuf;
 
378
 
 
379
      while (err > 0) {
 
380
        struct tree_data *my_data;
 
381
 
 
382
        dirlen = dirp->dirlen;
 
383
 
 
384
        my_data = make_tree_data(dirp->smbc_type, dirp->name);
 
385
 
 
386
        if (!my_data) {
 
387
 
 
388
          g_print("Could not allocate space for tree_data: %s\n",
 
389
                  dirp->name);
 
390
 
 
391
          gtk_main_quit();
 
392
          return;
 
393
 
 
394
        }
 
395
 
 
396
        aitem = gtk_tree_item_new_with_label(dirp->name);
 
397
 
 
398
        /* Connect all GtkItem:: and GtkTreeItem:: signals */
 
399
        gtk_signal_connect (GTK_OBJECT(aitem), "select",
 
400
                            GTK_SIGNAL_FUNC(cb_itemsignal), "select");
 
401
        gtk_signal_connect (GTK_OBJECT(aitem), "deselect",
 
402
                            GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
 
403
        gtk_signal_connect (GTK_OBJECT(aitem), "toggle",
 
404
                            GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
 
405
        gtk_signal_connect (GTK_OBJECT(aitem), "expand",
 
406
                            GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
 
407
        gtk_signal_connect (GTK_OBJECT(aitem), "collapse",
 
408
                            GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
 
409
        /* Add it to the parent tree */
 
410
        gtk_tree_append (GTK_TREE(real_tree), aitem);
 
411
 
 
412
        gtk_widget_show (aitem);
 
413
 
 
414
        gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data);
 
415
 
 
416
        fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
 
417
 
 
418
        if (dirp->smbc_type != SMBC_FILE &&
 
419
            dirp->smbc_type != SMBC_IPC_SHARE &&
 
420
            (strcmp(dirp->name, ".") != 0) && 
 
421
            (strcmp(dirp->name, "..") !=0)){
 
422
          
 
423
          subtree = gtk_tree_new();
 
424
          gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree);
 
425
 
 
426
          gtk_signal_connect(GTK_OBJECT(subtree), "select_child",
 
427
                             GTK_SIGNAL_FUNC(cb_select_child), real_tree);
 
428
          gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child",
 
429
                             GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
 
430
 
 
431
        }
 
432
 
 
433
        dirp = (struct smbc_dirent *) ((char *) dirp + dirlen);
 
434
        err -= dirlen;
 
435
 
 
436
      }
 
437
 
 
438
    }
 
439
 
 
440
    smbc_closedir(dh);   
 
441
 
 
442
  }
 
443
  else if (strncmp(signame, "collapse", 8) == 0) {
 
444
    GtkWidget *subtree = gtk_tree_new();
 
445
 
 
446
    gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children);
 
447
 
 
448
    gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
 
449
 
 
450
    gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
 
451
                        GTK_SIGNAL_FUNC(cb_select_child), real_tree);
 
452
    gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
 
453
                        GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
 
454
 
 
455
  }
 
456
 
 
457
}
 
458
 
 
459
static void cb_selection_changed( GtkWidget *tree )
 
460
{
 
461
  GList *i;
 
462
  
 
463
  g_print ("selection_change called for tree %p\n", tree);
 
464
  g_print ("selected objects are:\n");
 
465
 
 
466
  i = GTK_TREE_SELECTION(tree);
 
467
  while (i){
 
468
    gchar *name;
 
469
    GtkLabel *label;
 
470
    GtkWidget *item;
 
471
 
 
472
    /* Get a GtkWidget pointer from the list node */
 
473
    item = GTK_WIDGET (i->data);
 
474
    label = GTK_LABEL (GTK_BIN (item)->child);
 
475
    gtk_label_get (label, &name);
 
476
    g_print ("\t%s on level %d\n", name, GTK_TREE
 
477
             (item->parent)->level);
 
478
    i = i->next;
 
479
  }
 
480
}
 
481
 
 
482
/*
 
483
 * Expand or collapse the whole network ...
 
484
 */
 
485
static void cb_wholenet(GtkWidget *item, gchar *signame)
 
486
{
 
487
  GtkWidget *real_tree, *aitem, *subtree;
 
488
  gchar *name;
 
489
  GtkLabel *label;
 
490
  gint dh, err, dirlen;
 
491
  char dirbuf[512];
 
492
  struct smbc_dirent *dirp;
 
493
  
 
494
  label = GTK_LABEL (GTK_BIN (item)->child);
 
495
  gtk_label_get (label, &name);
 
496
  g_print ("%s called for item %s->%p, level %d\n", signame, name,
 
497
           item, GTK_TREE (item->parent)->level);
 
498
 
 
499
  real_tree = GTK_TREE_ITEM_SUBTREE(item);  /* Get the subtree */
 
500
 
 
501
  if (strncmp(signame, "expand", 6) == 0) { /* Expand called */
 
502
 
 
503
    if ((dh = smbc_opendir("smb://")) < 0) { /* Handle error */
 
504
 
 
505
      g_print("cb_wholenet: Could not open dir smbc://, %s\n",
 
506
              strerror(errno));
 
507
 
 
508
      gtk_main_quit();
 
509
 
 
510
      return;
 
511
 
 
512
    }
 
513
 
 
514
    while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 
 
515
                                sizeof(dirbuf))) != 0) {
 
516
 
 
517
      if (err < 0) { /* An error, report it */
 
518
 
 
519
        g_print("cb_wholenet: Could not read dir smbc://, %s\n",
 
520
                strerror(errno));
 
521
 
 
522
        gtk_main_quit();
 
523
 
 
524
        return;
 
525
 
 
526
      }
 
527
 
 
528
      dirp = (struct smbc_dirent *)dirbuf;
 
529
 
 
530
      while (err > 0) {
 
531
        struct tree_data *my_data;
 
532
 
 
533
        dirlen = dirp->dirlen;
 
534
 
 
535
        my_data = make_tree_data(dirp->smbc_type, dirp->name);
 
536
 
 
537
        aitem = gtk_tree_item_new_with_label(dirp->name);
 
538
 
 
539
        /* Connect all GtkItem:: and GtkTreeItem:: signals */
 
540
        gtk_signal_connect (GTK_OBJECT(aitem), "select",
 
541
                            GTK_SIGNAL_FUNC(cb_itemsignal), "select");
 
542
        gtk_signal_connect (GTK_OBJECT(aitem), "deselect",
 
543
                            GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
 
544
        gtk_signal_connect (GTK_OBJECT(aitem), "toggle",
 
545
                            GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
 
546
        gtk_signal_connect (GTK_OBJECT(aitem), "expand",
 
547
                            GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
 
548
        gtk_signal_connect (GTK_OBJECT(aitem), "collapse",
 
549
                            GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
 
550
 
 
551
        gtk_tree_append (GTK_TREE(real_tree), aitem);
 
552
        /* Show it - this can be done at any time */
 
553
        gtk_widget_show (aitem);
 
554
 
 
555
        gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data);
 
556
 
 
557
        fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
 
558
 
 
559
        subtree = gtk_tree_new();
 
560
 
 
561
        gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree);
 
562
 
 
563
        gtk_signal_connect(GTK_OBJECT(subtree), "select_child",
 
564
                           GTK_SIGNAL_FUNC(cb_select_child), real_tree);
 
565
        gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child",
 
566
                           GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
 
567
 
 
568
        dirp = (struct smbc_dirent *) ((char *) dirp + dirlen);
 
569
        err -= dirlen;
 
570
 
 
571
      }
 
572
 
 
573
    }
 
574
 
 
575
    smbc_closedir(dh);   
 
576
 
 
577
  }
 
578
  else { /* Must be collapse ... FIXME ... */
 
579
    GtkWidget *subtree = gtk_tree_new();
 
580
 
 
581
    gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children);
 
582
 
 
583
    gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
 
584
 
 
585
    gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
 
586
                        GTK_SIGNAL_FUNC(cb_select_child), real_tree);
 
587
    gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
 
588
                        GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
 
589
 
 
590
 
 
591
  }
 
592
 
 
593
}
 
594
 
 
595
/* Should put up a dialog box to ask the user for username and password */
 
596
 
 
597
static void 
 
598
auth_fn(const char *server, const char *share,
 
599
        char *workgroup, int wgmaxlen, char *username, int unmaxlen,
 
600
        char *password, int pwmaxlen)
 
601
{
 
602
 
 
603
   strncpy(username, "test", unmaxlen);
 
604
   strncpy(password, "test", pwmaxlen);
 
605
 
 
606
}
 
607
 
 
608
static char *col_titles[] = {
 
609
  "Name", "Attributes", "Size", "Modification Date",
 
610
};
 
611
 
 
612
int main( int   argc,
 
613
          char *argv[] )
 
614
{
 
615
  GtkWidget *window, *scrolled_win, *scrolled_win2, *tree;
 
616
  GtkWidget *subtree, *item, *main_hbox, *r_pane, *l_pane;
 
617
  gint err, dh;
 
618
  gint i;
 
619
  char dirbuf[512];
 
620
  struct smbc_dirent *dirp;
 
621
 
 
622
  gtk_init (&argc, &argv);
 
623
 
 
624
  /* Init the smbclient library */
 
625
 
 
626
  err = smbc_init(auth_fn, 10);
 
627
 
 
628
  /* Print an error response ... */
 
629
 
 
630
  if (err < 0) {
 
631
 
 
632
    fprintf(stderr, "smbc_init returned %s (%i)\nDo you have a ~/.smb/smb.conf file?\n", strerror(errno), errno);
 
633
    exit(1);
 
634
 
 
635
  }
 
636
 
 
637
  /* a generic toplevel window */
 
638
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
639
  gtk_widget_set_name(window, "main browser window");
 
640
  gtk_signal_connect (GTK_OBJECT(window), "delete_event",
 
641
                      GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
 
642
  gtk_window_set_title(GTK_WINDOW(window), "The Linux Windows Network Browser");
 
643
  gtk_widget_set_usize(GTK_WIDGET(window), 750, -1);
 
644
  gtk_container_set_border_width (GTK_CONTAINER(window), 5);
 
645
 
 
646
  gtk_widget_show (window);
 
647
 
 
648
  /* A container for the two panes ... */
 
649
 
 
650
  main_hbox = gtk_hbox_new(FALSE, 1);
 
651
  gtk_container_border_width(GTK_CONTAINER(main_hbox), 1);
 
652
  gtk_container_add(GTK_CONTAINER(window), main_hbox);
 
653
 
 
654
  gtk_widget_show(main_hbox);
 
655
 
 
656
  l_pane = gtk_hpaned_new();
 
657
  gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
 
658
  r_pane = gtk_hpaned_new();
 
659
  gtk_paned_gutter_size(GTK_PANED(r_pane), (GTK_PANED(r_pane))->handle_size);
 
660
  gtk_container_add(GTK_CONTAINER(main_hbox), l_pane);
 
661
  gtk_widget_show(l_pane);
 
662
 
 
663
  /* A generic scrolled window */
 
664
  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
 
665
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
 
666
                                  GTK_POLICY_AUTOMATIC,
 
667
                                  GTK_POLICY_AUTOMATIC);
 
668
  gtk_widget_set_usize (scrolled_win, 150, 200);
 
669
  gtk_container_add (GTK_CONTAINER(l_pane), scrolled_win);
 
670
  gtk_widget_show (scrolled_win);
 
671
 
 
672
  /* Another generic scrolled window */
 
673
  scrolled_win2 = gtk_scrolled_window_new (NULL, NULL);
 
674
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win2),
 
675
                                  GTK_POLICY_AUTOMATIC,
 
676
                                  GTK_POLICY_AUTOMATIC);
 
677
  gtk_widget_set_usize (scrolled_win2, 150, 200);
 
678
  gtk_paned_add2 (GTK_PANED(l_pane), scrolled_win2);
 
679
  gtk_widget_show (scrolled_win2);
 
680
  
 
681
  /* Create the root tree */
 
682
  tree = gtk_tree_new();
 
683
  g_print ("root tree is %p\n", tree);
 
684
  /* connect all GtkTree:: signals */
 
685
  gtk_signal_connect (GTK_OBJECT(tree), "select_child",
 
686
                      GTK_SIGNAL_FUNC(cb_select_child), tree);
 
687
  gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
 
688
                      GTK_SIGNAL_FUNC(cb_unselect_child), tree);
 
689
  gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
 
690
                      GTK_SIGNAL_FUNC(cb_selection_changed), tree);
 
691
  /* Add it to the scrolled window */
 
692
  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
 
693
                                         tree);
 
694
  /* Set the selection mode */
 
695
  gtk_tree_set_selection_mode (GTK_TREE(tree),
 
696
                               GTK_SELECTION_MULTIPLE);
 
697
  /* Show it */
 
698
  gtk_widget_show (tree);
 
699
 
 
700
  /* Now, create a clist and attach it to the second pane */
 
701
 
 
702
  clist = gtk_clist_new_with_titles(4, col_titles);
 
703
 
 
704
  gtk_container_add (GTK_CONTAINER(scrolled_win2), clist);
 
705
 
 
706
  gtk_widget_show(clist);
 
707
 
 
708
  /* Now, build the top level display ... */
 
709
 
 
710
  if ((dh = smbc_opendir("smb://")) < 0) {
 
711
 
 
712
    fprintf(stderr, "Could not list workgroups: smb://: %s\n",
 
713
            strerror(errno));
 
714
 
 
715
    exit(1);
 
716
 
 
717
  }
 
718
 
 
719
  /* Create a tree item for Whole Network */
 
720
 
 
721
  item = gtk_tree_item_new_with_label ("Whole Network");
 
722
  /* Connect all GtkItem:: and GtkTreeItem:: signals */
 
723
  gtk_signal_connect (GTK_OBJECT(item), "select",
 
724
                      GTK_SIGNAL_FUNC(cb_itemsignal), "select");
 
725
  gtk_signal_connect (GTK_OBJECT(item), "deselect",
 
726
                      GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
 
727
  gtk_signal_connect (GTK_OBJECT(item), "toggle",
 
728
                      GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
 
729
  gtk_signal_connect (GTK_OBJECT(item), "expand",
 
730
                      GTK_SIGNAL_FUNC(cb_wholenet), "expand");
 
731
  gtk_signal_connect (GTK_OBJECT(item), "collapse",
 
732
                      GTK_SIGNAL_FUNC(cb_wholenet), "collapse");
 
733
  /* Add it to the parent tree */
 
734
  gtk_tree_append (GTK_TREE(tree), item);
 
735
  /* Show it - this can be done at any time */
 
736
  gtk_widget_show (item);
 
737
 
 
738
  subtree = gtk_tree_new();  /* A subtree for Whole Network */
 
739
 
 
740
  gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
 
741
 
 
742
  gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
 
743
                      GTK_SIGNAL_FUNC(cb_select_child), tree);
 
744
  gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
 
745
                      GTK_SIGNAL_FUNC(cb_unselect_child), tree);
 
746
 
 
747
  /* Now, get the items in smb:/// and add them to the tree */
 
748
 
 
749
  while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 
 
750
                              sizeof(dirbuf))) != 0) {
 
751
 
 
752
    if (err < 0) { /* Handle the error */
 
753
 
 
754
      fprintf(stderr, "Could not read directory for smbc:///: %s\n",
 
755
              strerror(errno));
 
756
 
 
757
      exit(1);
 
758
 
 
759
    }
 
760
 
 
761
    dirp = (struct smbc_dirent *)dirbuf;
 
762
 
 
763
    fprintf(stdout, "Dir len: %u\n", err);
 
764
 
 
765
    while (err > 0) { /* Extract each entry and make a sub-tree */
 
766
      struct tree_data *my_data;
 
767
      int dirlen = dirp->dirlen;
 
768
 
 
769
      my_data = make_tree_data(dirp->smbc_type, dirp->name);
 
770
 
 
771
      item = gtk_tree_item_new_with_label(dirp->name);
 
772
      /* Connect all GtkItem:: and GtkTreeItem:: signals */
 
773
      gtk_signal_connect (GTK_OBJECT(item), "select",
 
774
                          GTK_SIGNAL_FUNC(cb_itemsignal), "select");
 
775
      gtk_signal_connect (GTK_OBJECT(item), "deselect",
 
776
                          GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
 
777
      gtk_signal_connect (GTK_OBJECT(item), "toggle",
 
778
                          GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
 
779
      gtk_signal_connect (GTK_OBJECT(item), "expand",
 
780
                          GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
 
781
      gtk_signal_connect (GTK_OBJECT(item), "collapse",
 
782
                          GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
 
783
      /* Add it to the parent tree */
 
784
      gtk_tree_append (GTK_TREE(tree), item);
 
785
      /* Show it - this can be done at any time */
 
786
      gtk_widget_show (item);
 
787
 
 
788
      gtk_object_set_user_data(GTK_OBJECT(item), (gpointer)my_data);
 
789
 
 
790
      fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
 
791
 
 
792
      subtree = gtk_tree_new();
 
793
 
 
794
      gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
 
795
 
 
796
      gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
 
797
                          GTK_SIGNAL_FUNC(cb_select_child), tree);
 
798
      gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
 
799
                          GTK_SIGNAL_FUNC(cb_unselect_child), tree);
 
800
 
 
801
      dirp = (struct smbc_dirent *) ((char *) dirp + dirlen);
 
802
      err -= dirlen;
 
803
 
 
804
    }
 
805
 
 
806
  }
 
807
 
 
808
  smbc_closedir(dh); /* FIXME, check for error :-) */
 
809
 
 
810
  /* Show the window and loop endlessly */
 
811
  gtk_main();
 
812
  return 0;
 
813
}
 
814
/* example-end */