2 Unix SMB/Netbios implementation.
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
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 2 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* example-gtk+ application, ripped off from the gtk+ tree.c sample */
29 #include "libsmbclient.h"
33 guint32 type; /* Type of tree item, an SMBC_TYPE */
34 char name[256]; /* May need to change this later */
39 * We are given a widget, and we want to retrieve its URL so we
40 * can do a directory listing.
42 * We walk back up the tree, picking up pieces until we hit a server or
43 * workgroup type and return a path from there
46 static char path_string[1024];
48 char *get_path(GtkWidget *item)
52 char *comps[1024]; /* We keep pointers to the components here */
53 int i = 0, j, level,type;
55 /* Walk back up the tree, getting the private data */
57 level = GTK_TREE(item->parent)->level;
59 /* Pick up this item's component info */
61 pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(item));
63 comps[i++] = pd->name;
66 while (level > 0 && type != SMBC_SERVER && type != SMBC_WORKGROUP) {
68 /* Find the parent and extract the data etc ... */
70 p = GTK_WIDGET(p->parent);
71 p = GTK_WIDGET(GTK_TREE(p)->tree_owner);
73 pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(p));
75 level = GTK_TREE(item->parent)->level;
77 comps[i++] = pd->name;
83 * Got a list of comps now, should check that we did not hit a workgroup
84 * when we got other things as well ... Later
89 snprintf(path_string, sizeof(path_string), "smb:/");
91 for (j = i - 1; j >= 0; j--) {
93 strncat(path_string, "/", sizeof(path_string) - strlen(path_string));
94 strncat(path_string, comps[j], sizeof(path_string) - strlen(path_string));
98 fprintf(stdout, "Path string = %s\n", path_string);
104 struct tree_data *make_tree_data(guint32 type, const char *name)
106 struct tree_data *p = (struct tree_data *)malloc(sizeof(struct tree_data));
111 strncpy(p->name, name, sizeof(p->name));
119 /* for all the GtkItem:: and GtkTreeItem:: signals */
120 static void cb_itemsignal( GtkWidget *item,
123 GtkWidget *real_tree, *aitem, *subtree;
126 gint dh, err, dirlen, level;
128 struct smbc_dirent *dirp;
130 label = GTK_LABEL (GTK_BIN (item)->child);
131 /* Get the text of the label */
132 gtk_label_get (label, &name);
134 level = GTK_TREE(item->parent)->level;
136 /* Get the level of the tree which the item is in */
137 g_print ("%s called for item %s->%p, level %d\n", signame, name,
138 item, GTK_TREE (item->parent)->level);
140 if (strncmp(signame, "expand", 6) == 0) { /* Expand called */
143 if ((dh = smbc_opendir(get_path(item))) < 0) { /* Handle error */
145 g_print("cb_wholenet: Could not open dir %s, %s\n", server,
154 real_tree = GTK_TREE_ITEM_SUBTREE(item); /* Get the subtree */
156 while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf,
157 sizeof(dirbuf))) != 0) {
159 if (err < 0) { /* An error, report it */
161 g_print("cb_wholenet: Could not read dir smbc://, %s\n",
170 dirp = (struct smbc_dirent *)dirbuf;
173 struct tree_data *my_data;
175 dirlen = dirp->dirlen;
177 my_data = make_tree_data(dirp->smbc_type, dirp->name);
181 g_print("Could not allocate space for tree_data: %s\n",
189 aitem = gtk_tree_item_new_with_label(dirp->name);
191 /* Connect all GtkItem:: and GtkTreeItem:: signals */
192 gtk_signal_connect (GTK_OBJECT(aitem), "select",
193 GTK_SIGNAL_FUNC(cb_itemsignal), "select");
194 gtk_signal_connect (GTK_OBJECT(aitem), "deselect",
195 GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
196 gtk_signal_connect (GTK_OBJECT(aitem), "toggle",
197 GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
198 gtk_signal_connect (GTK_OBJECT(aitem), "expand",
199 GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
200 gtk_signal_connect (GTK_OBJECT(aitem), "collapse",
201 GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
202 /* Add it to the parent tree */
203 gtk_tree_append (GTK_TREE(real_tree), aitem);
205 gtk_widget_show (aitem);
207 gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data);
209 fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
211 if (dirp->smbc_type != SMBC_FILE && dirp->smbc_type != SMBC_IPC_SHARE){
213 subtree = gtk_tree_new();
214 gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree);
218 (char *)dirp += dirlen;
231 /* Note that this is never called */
232 static void cb_unselect_child( GtkWidget *root_tree,
236 g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
237 root_tree, subtree, child);
240 /* Note that this is called every time the user clicks on an item,
241 whether it is already selected or not. */
242 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
245 g_print ("select_child called for root tree %p, subtree %p, child %p\n",
246 root_tree, subtree, child);
249 static void cb_selection_changed( GtkWidget *tree )
253 g_print ("selection_change called for tree %p\n", tree);
254 g_print ("selected objects are:\n");
256 i = GTK_TREE_SELECTION(tree);
262 /* Get a GtkWidget pointer from the list node */
263 item = GTK_WIDGET (i->data);
264 label = GTK_LABEL (GTK_BIN (item)->child);
265 gtk_label_get (label, &name);
266 g_print ("\t%s on level %d\n", name, GTK_TREE
267 (item->parent)->level);
273 * Expand or collapse the whole network ...
275 static void cb_wholenet(GtkWidget *item, gchar *signame)
277 GtkWidget *real_tree, *aitem, *subtree;
280 gint dh, err, dirlen;
282 struct smbc_dirent *dirp;
284 label = GTK_LABEL (GTK_BIN (item)->child);
285 gtk_label_get (label, &name);
286 g_print ("%s called for item %s->%p, level %d\n", signame, name,
287 item, GTK_TREE (item->parent)->level);
289 if (strncmp(signame, "expand", 6) == 0) { /* Expand called */
291 if ((dh = smbc_opendir("smb://")) < 0) { /* Handle error */
293 g_print("cb_wholenet: Could not open dir smbc://, %s\n",
302 real_tree = GTK_TREE_ITEM_SUBTREE(item); /* Get the subtree */
304 while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf,
305 sizeof(dirbuf))) != 0) {
307 if (err < 0) { /* An error, report it */
309 g_print("cb_wholenet: Could not read dir smbc://, %s\n",
318 dirp = (struct smbc_dirent *)dirbuf;
321 struct tree_data *my_data;
323 dirlen = dirp->dirlen;
325 my_data = make_tree_data(dirp->smbc_type, dirp->name);
327 aitem = gtk_tree_item_new_with_label(dirp->name);
329 /* Connect all GtkItem:: and GtkTreeItem:: signals */
330 gtk_signal_connect (GTK_OBJECT(aitem), "select",
331 GTK_SIGNAL_FUNC(cb_itemsignal), "select");
332 gtk_signal_connect (GTK_OBJECT(aitem), "deselect",
333 GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
334 gtk_signal_connect (GTK_OBJECT(aitem), "toggle",
335 GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
336 gtk_signal_connect (GTK_OBJECT(aitem), "expand",
337 GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
338 gtk_signal_connect (GTK_OBJECT(aitem), "collapse",
339 GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
341 gtk_tree_append (GTK_TREE(real_tree), aitem);
342 /* Show it - this can be done at any time */
343 gtk_widget_show (aitem);
345 gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data);
347 fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
349 subtree = gtk_tree_new();
351 gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree);
353 (char *)dirp += dirlen;
367 auth_fn(char *server, char *share,
368 char **workgroup, char **username, char **password)
380 GtkWidget *window, *scrolled_win, *tree;
381 GtkWidget *subtree, *item;
385 struct smbc_dirent *dirp;
387 gtk_init (&argc, &argv);
389 /* Init the smbclient library */
391 err = smbc_init(auth_fn, "", 10);
393 /* a generic toplevel window */
394 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
395 gtk_signal_connect (GTK_OBJECT(window), "delete_event",
396 GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
397 gtk_container_set_border_width (GTK_CONTAINER(window), 5);
399 /* A generic scrolled window */
400 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
401 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
402 GTK_POLICY_AUTOMATIC,
403 GTK_POLICY_AUTOMATIC);
404 gtk_widget_set_usize (scrolled_win, 150, 200);
405 gtk_container_add (GTK_CONTAINER(window), scrolled_win);
406 gtk_widget_show (scrolled_win);
408 /* Create the root tree */
409 tree = gtk_tree_new();
410 g_print ("root tree is %p\n", tree);
411 /* connect all GtkTree:: signals */
412 gtk_signal_connect (GTK_OBJECT(tree), "select_child",
413 GTK_SIGNAL_FUNC(cb_select_child), tree);
414 gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
415 GTK_SIGNAL_FUNC(cb_unselect_child), tree);
416 gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
417 GTK_SIGNAL_FUNC(cb_selection_changed), tree);
418 /* Add it to the scrolled window */
419 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
421 /* Set the selection mode */
422 gtk_tree_set_selection_mode (GTK_TREE(tree),
423 GTK_SELECTION_MULTIPLE);
425 gtk_widget_show (tree);
427 /* Now, build the top level display ... */
429 if ((dh = smbc_opendir("smb:///")) < 0) {
431 fprintf(stderr, "Could not list default workgroup: smb:///: %s\n",
438 /* Create a tree item for Whole Network */
440 item = gtk_tree_item_new_with_label ("Whole Network");
441 /* Connect all GtkItem:: and GtkTreeItem:: signals */
442 gtk_signal_connect (GTK_OBJECT(item), "select",
443 GTK_SIGNAL_FUNC(cb_itemsignal), "select");
444 gtk_signal_connect (GTK_OBJECT(item), "deselect",
445 GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
446 gtk_signal_connect (GTK_OBJECT(item), "toggle",
447 GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
448 gtk_signal_connect (GTK_OBJECT(item), "expand",
449 GTK_SIGNAL_FUNC(cb_wholenet), "expand");
450 gtk_signal_connect (GTK_OBJECT(item), "collapse",
451 GTK_SIGNAL_FUNC(cb_wholenet), "collapse");
452 /* Add it to the parent tree */
453 gtk_tree_append (GTK_TREE(tree), item);
454 /* Show it - this can be done at any time */
455 gtk_widget_show (item);
457 subtree = gtk_tree_new(); /* A subtree for Whole Network */
459 gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
461 /* Now, get the items in smb:/// and add them to the tree */
463 dirp = (struct smbc_dirent *)dirbuf;
465 while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf,
466 sizeof(dirbuf))) != 0) {
468 if (err < 0) { /* Handle the error */
470 fprintf(stderr, "Could not read directory for smbc:///: %s\n",
477 fprintf(stdout, "Dir len: %u\n", err);
479 while (err > 0) { /* Extract each entry and make a sub-tree */
480 struct tree_data *my_data;
481 int dirlen = dirp->dirlen;
483 my_data = make_tree_data(dirp->smbc_type, dirp->name);
485 item = gtk_tree_item_new_with_label(dirp->name);
486 /* Connect all GtkItem:: and GtkTreeItem:: signals */
487 gtk_signal_connect (GTK_OBJECT(item), "select",
488 GTK_SIGNAL_FUNC(cb_itemsignal), "select");
489 gtk_signal_connect (GTK_OBJECT(item), "deselect",
490 GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
491 gtk_signal_connect (GTK_OBJECT(item), "toggle",
492 GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
493 gtk_signal_connect (GTK_OBJECT(item), "expand",
494 GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
495 gtk_signal_connect (GTK_OBJECT(item), "collapse",
496 GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
497 /* Add it to the parent tree */
498 gtk_tree_append (GTK_TREE(tree), item);
499 /* Show it - this can be done at any time */
500 gtk_widget_show (item);
502 gtk_object_set_user_data(GTK_OBJECT(item), (gpointer)my_data);
504 fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
506 subtree = gtk_tree_new();
508 gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);
510 (char *)dirp += dirlen;
517 smbc_closedir(dh); /* FIXME, check for error :-) */
519 /* Show the window and loop endlessly */
520 gtk_widget_show (window);