Patch: file share support for Nautilus



The following patch add file share support for Nautilus :
initialy, this feature has been developed at MandrakeSoft to provide an
easy way for users to share directories in their home using either NFS
or SMB.. It was done for both Konqueror and Nautilus (that is why there
is a script in perl to do the nfs/samba file modification). KDE part has
been merged in KDE 3.1 branch...

Of course, this is a first version of the patch (it should work
correctly, it was shipped with nautilus 1.0.6 on Mandrake 8.2), comments
are welcome so we can merge this killer feature :))

-- 
Frédéric Crozat
MandrakeSoft
? fileshare.patch
? nautilus-2.0.0-sharing.patch.bz2
? nautilus-2.0.0-supermount.patch.bz2
? stamp-h1
? stamp-h1.in
? stamp-h2.in
? stamp-h3.in
? stamp-h4.in
? supermount.patch
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/nautilus/ChangeLog,v
retrieving revision 1.5398
diff -u -r1.5398 ChangeLog
--- ChangeLog	29 Jun 2002 03:58:33 -0000	1.5398
+++ ChangeLog	1 Jul 2002 14:27:49 -0000
@@ -1,3 +1,32 @@
+2002-07-01  Frederic Crozat  <fcrozat mandrakesoft com>
+
+	* data/Makefile.am:
+	* data/filesharelist:
+	* data/fileshareset:
+	* icons/default/Makefile.am:
+	* icons/default/emblem-shared.svg:
+	* libnautilus-private/nautilus-file.c: (update_file),
+	(refresh_shared_directories),
+	(fileshare_config_has_changed_callback),
+	(nautilus_file_initialize_share_monitor),
+	(nautilus_file_can_share_directories), (nautilus_file_is_shared),
+	(nautilus_file_set_shared), (get_automatic_emblems_as_integer),
+	(prepend_automatic_emblem_names), (nautilus_file_class_init):
+	* libnautilus-private/nautilus-file.h:
+	* src/file-manager/fm-directory-view.c:
+	(open_properties_window_callback), (open_share_properties_window),
+	(real_merge_menus), (real_update_menus):
+	* src/file-manager/fm-properties-window.c: (should_show_share),
+	(startup_data_new), (update_share_tab), (update_share_property),
+	(fileshare_config_exec), (disable_share_property),
+	(launch_filesharing_callback), (share_changed),
+	(create_share_page), (create_properties_window),
+	(fm_properties_window_show_share), (fm_properties_window_present),
+	(real_fm_properties_window_present):
+	* src/file-manager/fm-properties-window.h:
+	* src/file-manager/nautilus-directory-view-ui.xml:
+	Add support for file sharing through NFS or SMB
+
 2002-06-29  Gregory Merchan  <merchan phys lsu edu>
 
 	* src/nautilus-desktop-window.c:
Index: data/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/data/Makefile.am,v
retrieving revision 1.19
diff -u -r1.19 Makefile.am
--- data/Makefile.am	2 May 2002 21:16:27 -0000	1.19
+++ data/Makefile.am	1 Jul 2002 14:27:49 -0000
@@ -37,6 +37,8 @@
 	nautilus-suggested.placeholder 	\
 	starthere.desktop		\
 	starthere-link.desktop		\
+	fileshareset			\
+	filesharelist			\
 	$(NULL)
 
 EXTRA_DIST = $(nautilusdata_DATA) \
Index: data/filesharelist
===================================================================
RCS file: data/filesharelist
diff -N data/filesharelist
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ data/filesharelist	1 Jul 2002 14:27:49 -0000
@@ -0,0 +1,388 @@
+#!/usr/bin/perl -T
+use strict;
+
+########################################
+# config files
+$nfs_exports::default_options = '*(ro,all_squash)';
+$nfs_exports::conf_file = '/etc/exports';
+$smb_exports::conf_file = '/etc/samba/smb.conf';
+my $authorisation_file = '/etc/security/fileshare.conf';
+my $authorisation_group = 'fileshare';
+
+
+########################################
+# fileshare utility $Id: fileshareset,v 1.10 2002/03/06 23:13:22 prigaux Exp $
+# Copyright (C) 2001-2002 MandrakeSoft (pixel mandrakesoft com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+########################################
+my $uid = $<;
+my $username = getpwuid($uid);
+
+########################################
+# errors
+my $usage =
+"usage: fileshareset --add <dir>
+       fileshareset --remove <dir>";
+my $non_authorised =
+qq(You are not authorised to use fileshare'ing
+To grant you the rights:
+- put "RESTRICT=no" in $authorisation_file
+- or put user "$username" in group "$authorisation_group");
+my $no_export_method = "can't export anything: no nfs, no smb";
+
+my %exit_codes = reverse (
+  1 => $non_authorised,
+  2 => $usage,
+
+# when adding
+  3 => "already exported", 
+  4 => "invalid mount point",
+
+# when removing
+  5 => "not exported",
+
+  6 => $no_export_method,
+
+  255 => "various",
+);
+
+################################################################################
+# correct PATH needed to call /etc/init.d/... ? seems not, but...
+%ENV = ();#(PATH => '/bin:/sbin:/usr/bin:/usr/sbin');
+
+my $modify = $0 =~ /fileshareset/;
+
+authorisation::check($modify);
+
+my @exports = (
+	       -e $nfs_exports::conf_file ? nfs_exports::read() : (),
+	       -e $smb_exports::conf_file ? smb_exports::read() : (),
+	      );
+ exports or error($no_export_method);
+
+if ($modify) {
+    my ($cmd, $dir) = @ARGV;
+    $< = $>;
+    @ARGV == 2 && ($cmd eq '--add' || $cmd eq '--remove') or error($usage);
+
+    verify_mntpoint($dir);
+
+    if ($cmd eq '--add') {
+	my @errs = map { eval { $_->add($dir) }; $@ } @exports;
+	grep { !$_ } @errs or error("already exported");
+    } else {
+	my @errs = map { eval { $_->remove($dir) }; $@ } @exports;
+	grep { !$_ } @errs or error("not exported");
+    }    
+    foreach my $export (@exports) {
+	$export->write;
+	$export->update_server;
+    }
+}
+my @mntpoints = grep {$_} uniq(map { map { $_->{mntpoint} } @$_ } @exports);
+print "$_\n" foreach grep { own($_) } @mntpoints;
+
+
+sub own { $uid == 0 || (stat($_[0]))[4] == $uid }
+
+sub verify_mntpoint {
+    local ($_) = @_;
+    my $ok = 1;
+    $ok &&= m|^/|;
+    $ok &&= !m|/../|;
+    $ok &&= !m|[\0\n\r]|;
+    $ok &&= -d $_;
+    $ok &&= own($_);
+    $ok or error("invalid mount point");
+}
+
+sub error {
+    my ($string) = @_;
+    print STDERR "$string\n";
+    exit($exit_codes{$string} || 255);
+}
+sub member { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 }
+sub uniq { my %l; $l{$_} = 1 foreach @_; grep { delete $l{$_} } @_ }
+
+
+################################################################################
+package authorisation;
+
+sub read_conf {
+    my ($exclusive_lock) = @_;
+    open F_lock, $authorisation_file; # don't care if it's missing
+    flock(F_lock, $exclusive_lock ? 2 : 1) or die "can't lock";
+    my %conf;
+    foreach (<F_lock>) {
+	s/#.*//; # remove comments
+	s/^\s+//; 
+	s/\s+$//;
+	/^$/ and next;
+	my ($cmd, $value) = split('=', $_, 2);
+	$conf{$cmd} = $value || warn qq(suspicious line "$_" in $authorisation_file\n);
+    }
+    # no close F_lock, keep it locked
+    \%conf
+}
+
+sub check {
+    my ($exclusive_lock) = @_;
+    my $conf = read_conf($exclusive_lock);
+
+    if (lc($conf->{RESTRICT}) eq 'no') {
+	# ok, access granted for everybody
+    } else {
+	my @l;
+	while (@l = getgrent) {
+	    last if $l[0] eq $authorisation_group;
+	}
+	::member($username, split(' ', $l[3])) or ::error($non_authorised);
+    }
+}
+
+################################################################################
+package exports;
+
+sub find {
+    my ($exports, $mntpoint) = @_;
+    foreach (@$exports) {
+	$_->{mntpoint} eq $mntpoint and return $_;
+    }
+    undef;
+}
+
+sub add {
+    my ($exports, $mntpoint) = @_;
+    foreach (@$exports) {
+	$_->{mntpoint} eq $mntpoint and die 'add';
+    }
+    push @$exports, my $e = { mntpoint => $mntpoint };
+    $e;
+}
+
+sub remove {
+    my ($exports, $mntpoint) = @_;
+    my @l = grep { $_->{mntpoint} ne $mntpoint } @$exports;
+    @l < @$exports or die 'remove';
+    @$exports = @l;  
+}
+
+
+################################################################################
+package nfs_exports;
+
+use vars qw(@ISA $conf_file $default_options);
+BEGIN { @ISA = 'exports' }
+
+sub read {
+    my $file = $conf_file;
+    local *F;
+    open F, $file or return [];
+
+    my ($prev_raw, $prev_line, %e, @l);
+    my $line_nb = 0;
+    foreach my $raw (<F>) {
+	$line_nb++;
+	local $_ = $raw;
+	$raw .= "\n" if !/\n/;
+
+	s/#.*//; # remove comments
+
+	s/^\s+//; 
+	s/\s+$//; # remove unuseful spaces to help regexps
+
+	if (/^$/) {
+	    # blank lines ignored
+	    $prev_raw .= $raw;
+	    next;
+	}
+
+	if (/\\$/) {
+	    # line continue across lines
+	    chop; # remove the backslash
+	    $prev_line .= "$_ ";
+	    $prev_raw .= $raw;
+	    next;
+	}
+	my $line = $prev_line . $_;
+	my $raw_line = $prev_raw . $raw;
+	($prev_line, $prev_raw) = ('', '');
+
+	my ($mntpoint, $options) = $line =~ /("[^"]*"|\S+)\s+(.*)/ or die "$file:$line_nb: bad line $line\n";
+
+	# You can also specify spaces or any other unusual characters in the
+	# export path name using a backslash followed by the character code as
+	# 3 octal digits.
+	$mntpoint =~ s/\\(\d{3})/chr(oct $1)/ge;
+
+	# not accepting weird characters that would break the output
+	$mntpoint =~ m/[\0\n\r]/ and die "i won't handle this";
+	push @l, { mntpoint => $mntpoint, option => $options, raw => $raw_line };
+    }
+    bless \ l, 'nfs_exports';
+}
+
+sub write {
+    my ($nfs_exports) = @_;
+    foreach (@$nfs_exports) {
+	if (!exists $_->{options}) {
+	    $_->{options} = $default_options;
+	}
+	if (!exists $_->{raw}) {	    
+	    my $mntpoint = $_->{mntpoint} =~ /\s/ ? qq("$_->{mntpoint}") : $_->{mntpoint};
+	    $_->{raw} = sprintf("%s %s\n", $mntpoint, $_->{options});
+	}
+    }
+    local *F;
+    open F, ">$conf_file" or die "can't write $conf_file";
+    print F $_->{raw} foreach @$nfs_exports;
+}
+
+sub update_server {
+    if (fork) {
+	system('/usr/sbin/exportfs', '-r');
+	if (system('/sbin/pidof rpc.mountd >/dev/null') != 0 ||
+	    system('/sbin/pidof nfsd >/dev/null') != 0) {
+	    # trying to start the server...
+	    system('/etc/init.d/portmap start') if system('/etc/init.d/portmap status') != 0;
+	    system('/etc/init.d/nfs', $_) foreach 'stop', 'start';
+	}
+	exit 0;
+    }
+}
+
+################################################################################
+package smb_exports;
+
+use vars qw(@ISA $conf_file);
+BEGIN { @ISA = 'exports' }
+
+sub read {
+    my ($s, @l);
+    local *F;
+    open F, $conf_file;
+    local $_;
+    while (<F>) {
+	if (/^\s*\[.*\]/ || eof F) {
+	    #- first line in the category
+	    my ($label) = $s =~ /^\s*\[(.*)\]/;
+	    my ($mntpoint) = $s =~ /^\s*path\s*=\s*(.*)/m;
+	    push @l, { mntpoint => $mntpoint, raw => $s, label => $label };
+	    $s = '';
+	}
+	$s .= $_;
+    }
+    bless \ l, 'smb_exports';
+}
+
+sub write {
+    my ($smb_exports) = @_;
+    foreach (@$smb_exports) {
+	if (!exists $_->{raw}) {
+	    $_->{raw} = <<EOF;
+
+[$_->{label}]
+   path = $_->{mntpoint}
+   comment = $_->{mntpoint}
+   public = yes
+   guest ok = yes
+   writable = no
+EOF
+	}
+    }
+    local *F;
+    open F, ">$conf_file" or die "can't write $conf_file";
+    print F $_->{raw} foreach @$smb_exports;
+}
+
+sub add {
+    my ($exports, $mntpoint) = @_;
+    my $e = $exports->exports::add($mntpoint);
+    $e->{label} = name_mangle($mntpoint, map { $_->{label} } @$exports);
+}
+
+sub name_mangle {
+    my ($input, @others) = @_;
+
+    local $_ = $input;
+
+    # 1. first only keep legal characters. "/" is also kept for the moment
+    tr|a-z|A-Z|;
+    s|[^A-Z0-9#\-_!/]|_|g; # "$" is allowed except at the end, remove it in any case
+    
+    # 2. removing non-interesting parts
+    s|^/||;
+    s|^home/||;
+    s|_*/_*|/|g;
+    s|_+|_|g;
+
+    # 3. if size is too small (!), make it bigger
+    $_ .= "_" while length($_) < 3;
+
+    # 4. if size is too big, shorten it
+    while (length > 12) {
+	my ($s) = m|.*?/(.*)|;
+	if (length($s) > 8 && !grep { /\Q$s/ } @others) {
+	    # dropping leading directories when the resulting is still long and meaningful
+	    $_ = $s;
+	    next;
+	}
+	s|(.*)[0-9#\-_!/]|$1| and next;
+
+	# inspired by "Christian Brolin" "Long names are doom" on comp.lang.functional
+	s|(.+)[AEIOU]|$1| and next; # allButFirstVowels
+	s|(.*)(.)\2|$1$2| and next; # adjacentDuplicates
+
+	s|(.*).|$1|; # booh, :'-(
+    }
+
+    # 5. remove "/"s still there
+    s|/|_|g;
+
+    # 6. resolving conflicts
+    my $l = join("|", map { quotemeta } @others);
+    my $conflicts = qr|^($l)$|;
+    if (/$conflicts/) {
+      A: while (1) {
+	    for (my $nb = 1; length("$_$nb") <= 12; $nb++) {
+		if ("$_$nb" !~ /$conflicts/) {
+		    $_ = "$_$nb";
+		    last A;
+		}
+	    }
+	    $_ or die "can't find a unique name";
+	    # can't find a unique name, dropping the last letter
+	    s|(.*).|$1|;
+	}
+    }
+
+    # 7. done
+    $_;
+}
+
+sub update_server {
+    if (fork) {
+	system('/usr/bin/killall -HUP smbd 2>/dev/null');
+	if (system('/sbin/pidof smbd >/dev/null') != 0 ||
+	    system('/sbin/pidof nmbd >/dev/null') != 0) {
+	    # trying to start the server...
+	    system('/etc/init.d/smb', $_) foreach 'stop', 'start';
+	}
+	exit 0;
+    }
+}
Index: data/fileshareset
===================================================================
RCS file: data/fileshareset
diff -N data/fileshareset
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ data/fileshareset	1 Jul 2002 14:27:49 -0000
@@ -0,0 +1,388 @@
+#!/usr/bin/perl -T
+use strict;
+
+########################################
+# config files
+$nfs_exports::default_options = '*(ro,all_squash)';
+$nfs_exports::conf_file = '/etc/exports';
+$smb_exports::conf_file = '/etc/samba/smb.conf';
+my $authorisation_file = '/etc/security/fileshare.conf';
+my $authorisation_group = 'fileshare';
+
+
+########################################
+# fileshare utility $Id: fileshareset,v 1.10 2002/03/06 23:13:22 prigaux Exp $
+# Copyright (C) 2001-2002 MandrakeSoft (pixel mandrakesoft com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+########################################
+my $uid = $<;
+my $username = getpwuid($uid);
+
+########################################
+# errors
+my $usage =
+"usage: fileshareset --add <dir>
+       fileshareset --remove <dir>";
+my $non_authorised =
+qq(You are not authorised to use fileshare'ing
+To grant you the rights:
+- put "RESTRICT=no" in $authorisation_file
+- or put user "$username" in group "$authorisation_group");
+my $no_export_method = "can't export anything: no nfs, no smb";
+
+my %exit_codes = reverse (
+  1 => $non_authorised,
+  2 => $usage,
+
+# when adding
+  3 => "already exported", 
+  4 => "invalid mount point",
+
+# when removing
+  5 => "not exported",
+
+  6 => $no_export_method,
+
+  255 => "various",
+);
+
+################################################################################
+# correct PATH needed to call /etc/init.d/... ? seems not, but...
+%ENV = ();#(PATH => '/bin:/sbin:/usr/bin:/usr/sbin');
+
+my $modify = $0 =~ /fileshareset/;
+
+authorisation::check($modify);
+
+my @exports = (
+	       -e $nfs_exports::conf_file ? nfs_exports::read() : (),
+	       -e $smb_exports::conf_file ? smb_exports::read() : (),
+	      );
+ exports or error($no_export_method);
+
+if ($modify) {
+    my ($cmd, $dir) = @ARGV;
+    $< = $>;
+    @ARGV == 2 && ($cmd eq '--add' || $cmd eq '--remove') or error($usage);
+
+    verify_mntpoint($dir);
+
+    if ($cmd eq '--add') {
+	my @errs = map { eval { $_->add($dir) }; $@ } @exports;
+	grep { !$_ } @errs or error("already exported");
+    } else {
+	my @errs = map { eval { $_->remove($dir) }; $@ } @exports;
+	grep { !$_ } @errs or error("not exported");
+    }    
+    foreach my $export (@exports) {
+	$export->write;
+	$export->update_server;
+    }
+}
+my @mntpoints = grep {$_} uniq(map { map { $_->{mntpoint} } @$_ } @exports);
+print "$_\n" foreach grep { own($_) } @mntpoints;
+
+
+sub own { $uid == 0 || (stat($_[0]))[4] == $uid }
+
+sub verify_mntpoint {
+    local ($_) = @_;
+    my $ok = 1;
+    $ok &&= m|^/|;
+    $ok &&= !m|/../|;
+    $ok &&= !m|[\0\n\r]|;
+    $ok &&= -d $_;
+    $ok &&= own($_);
+    $ok or error("invalid mount point");
+}
+
+sub error {
+    my ($string) = @_;
+    print STDERR "$string\n";
+    exit($exit_codes{$string} || 255);
+}
+sub member { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 }
+sub uniq { my %l; $l{$_} = 1 foreach @_; grep { delete $l{$_} } @_ }
+
+
+################################################################################
+package authorisation;
+
+sub read_conf {
+    my ($exclusive_lock) = @_;
+    open F_lock, $authorisation_file; # don't care if it's missing
+    flock(F_lock, $exclusive_lock ? 2 : 1) or die "can't lock";
+    my %conf;
+    foreach (<F_lock>) {
+	s/#.*//; # remove comments
+	s/^\s+//; 
+	s/\s+$//;
+	/^$/ and next;
+	my ($cmd, $value) = split('=', $_, 2);
+	$conf{$cmd} = $value || warn qq(suspicious line "$_" in $authorisation_file\n);
+    }
+    # no close F_lock, keep it locked
+    \%conf
+}
+
+sub check {
+    my ($exclusive_lock) = @_;
+    my $conf = read_conf($exclusive_lock);
+
+    if (lc($conf->{RESTRICT}) eq 'no') {
+	# ok, access granted for everybody
+    } else {
+	my @l;
+	while (@l = getgrent) {
+	    last if $l[0] eq $authorisation_group;
+	}
+	::member($username, split(' ', $l[3])) or ::error($non_authorised);
+    }
+}
+
+################################################################################
+package exports;
+
+sub find {
+    my ($exports, $mntpoint) = @_;
+    foreach (@$exports) {
+	$_->{mntpoint} eq $mntpoint and return $_;
+    }
+    undef;
+}
+
+sub add {
+    my ($exports, $mntpoint) = @_;
+    foreach (@$exports) {
+	$_->{mntpoint} eq $mntpoint and die 'add';
+    }
+    push @$exports, my $e = { mntpoint => $mntpoint };
+    $e;
+}
+
+sub remove {
+    my ($exports, $mntpoint) = @_;
+    my @l = grep { $_->{mntpoint} ne $mntpoint } @$exports;
+    @l < @$exports or die 'remove';
+    @$exports = @l;  
+}
+
+
+################################################################################
+package nfs_exports;
+
+use vars qw(@ISA $conf_file $default_options);
+BEGIN { @ISA = 'exports' }
+
+sub read {
+    my $file = $conf_file;
+    local *F;
+    open F, $file or return [];
+
+    my ($prev_raw, $prev_line, %e, @l);
+    my $line_nb = 0;
+    foreach my $raw (<F>) {
+	$line_nb++;
+	local $_ = $raw;
+	$raw .= "\n" if !/\n/;
+
+	s/#.*//; # remove comments
+
+	s/^\s+//; 
+	s/\s+$//; # remove unuseful spaces to help regexps
+
+	if (/^$/) {
+	    # blank lines ignored
+	    $prev_raw .= $raw;
+	    next;
+	}
+
+	if (/\\$/) {
+	    # line continue across lines
+	    chop; # remove the backslash
+	    $prev_line .= "$_ ";
+	    $prev_raw .= $raw;
+	    next;
+	}
+	my $line = $prev_line . $_;
+	my $raw_line = $prev_raw . $raw;
+	($prev_line, $prev_raw) = ('', '');
+
+	my ($mntpoint, $options) = $line =~ /("[^"]*"|\S+)\s+(.*)/ or die "$file:$line_nb: bad line $line\n";
+
+	# You can also specify spaces or any other unusual characters in the
+	# export path name using a backslash followed by the character code as
+	# 3 octal digits.
+	$mntpoint =~ s/\\(\d{3})/chr(oct $1)/ge;
+
+	# not accepting weird characters that would break the output
+	$mntpoint =~ m/[\0\n\r]/ and die "i won't handle this";
+	push @l, { mntpoint => $mntpoint, option => $options, raw => $raw_line };
+    }
+    bless \ l, 'nfs_exports';
+}
+
+sub write {
+    my ($nfs_exports) = @_;
+    foreach (@$nfs_exports) {
+	if (!exists $_->{options}) {
+	    $_->{options} = $default_options;
+	}
+	if (!exists $_->{raw}) {	    
+	    my $mntpoint = $_->{mntpoint} =~ /\s/ ? qq("$_->{mntpoint}") : $_->{mntpoint};
+	    $_->{raw} = sprintf("%s %s\n", $mntpoint, $_->{options});
+	}
+    }
+    local *F;
+    open F, ">$conf_file" or die "can't write $conf_file";
+    print F $_->{raw} foreach @$nfs_exports;
+}
+
+sub update_server {
+    if (fork) {
+	system('/usr/sbin/exportfs', '-r');
+	if (system('/sbin/pidof rpc.mountd >/dev/null') != 0 ||
+	    system('/sbin/pidof nfsd >/dev/null') != 0) {
+	    # trying to start the server...
+	    system('/etc/init.d/portmap start') if system('/etc/init.d/portmap status') != 0;
+	    system('/etc/init.d/nfs', $_) foreach 'stop', 'start';
+	}
+	exit 0;
+    }
+}
+
+################################################################################
+package smb_exports;
+
+use vars qw(@ISA $conf_file);
+BEGIN { @ISA = 'exports' }
+
+sub read {
+    my ($s, @l);
+    local *F;
+    open F, $conf_file;
+    local $_;
+    while (<F>) {
+	if (/^\s*\[.*\]/ || eof F) {
+	    #- first line in the category
+	    my ($label) = $s =~ /^\s*\[(.*)\]/;
+	    my ($mntpoint) = $s =~ /^\s*path\s*=\s*(.*)/m;
+	    push @l, { mntpoint => $mntpoint, raw => $s, label => $label };
+	    $s = '';
+	}
+	$s .= $_;
+    }
+    bless \ l, 'smb_exports';
+}
+
+sub write {
+    my ($smb_exports) = @_;
+    foreach (@$smb_exports) {
+	if (!exists $_->{raw}) {
+	    $_->{raw} = <<EOF;
+
+[$_->{label}]
+   path = $_->{mntpoint}
+   comment = $_->{mntpoint}
+   public = yes
+   guest ok = yes
+   writable = no
+EOF
+	}
+    }
+    local *F;
+    open F, ">$conf_file" or die "can't write $conf_file";
+    print F $_->{raw} foreach @$smb_exports;
+}
+
+sub add {
+    my ($exports, $mntpoint) = @_;
+    my $e = $exports->exports::add($mntpoint);
+    $e->{label} = name_mangle($mntpoint, map { $_->{label} } @$exports);
+}
+
+sub name_mangle {
+    my ($input, @others) = @_;
+
+    local $_ = $input;
+
+    # 1. first only keep legal characters. "/" is also kept for the moment
+    tr|a-z|A-Z|;
+    s|[^A-Z0-9#\-_!/]|_|g; # "$" is allowed except at the end, remove it in any case
+    
+    # 2. removing non-interesting parts
+    s|^/||;
+    s|^home/||;
+    s|_*/_*|/|g;
+    s|_+|_|g;
+
+    # 3. if size is too small (!), make it bigger
+    $_ .= "_" while length($_) < 3;
+
+    # 4. if size is too big, shorten it
+    while (length > 12) {
+	my ($s) = m|.*?/(.*)|;
+	if (length($s) > 8 && !grep { /\Q$s/ } @others) {
+	    # dropping leading directories when the resulting is still long and meaningful
+	    $_ = $s;
+	    next;
+	}
+	s|(.*)[0-9#\-_!/]|$1| and next;
+
+	# inspired by "Christian Brolin" "Long names are doom" on comp.lang.functional
+	s|(.+)[AEIOU]|$1| and next; # allButFirstVowels
+	s|(.*)(.)\2|$1$2| and next; # adjacentDuplicates
+
+	s|(.*).|$1|; # booh, :'-(
+    }
+
+    # 5. remove "/"s still there
+    s|/|_|g;
+
+    # 6. resolving conflicts
+    my $l = join("|", map { quotemeta } @others);
+    my $conflicts = qr|^($l)$|;
+    if (/$conflicts/) {
+      A: while (1) {
+	    for (my $nb = 1; length("$_$nb") <= 12; $nb++) {
+		if ("$_$nb" !~ /$conflicts/) {
+		    $_ = "$_$nb";
+		    last A;
+		}
+	    }
+	    $_ or die "can't find a unique name";
+	    # can't find a unique name, dropping the last letter
+	    s|(.*).|$1|;
+	}
+    }
+
+    # 7. done
+    $_;
+}
+
+sub update_server {
+    if (fork) {
+	system('/usr/bin/killall -HUP smbd 2>/dev/null');
+	if (system('/sbin/pidof smbd >/dev/null') != 0 ||
+	    system('/sbin/pidof nmbd >/dev/null') != 0) {
+	    # trying to start the server...
+	    system('/etc/init.d/smb', $_) foreach 'stop', 'start';
+	}
+	exit 0;
+    }
+}
Index: icons/default/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/icons/default/Makefile.am,v
retrieving revision 1.9
diff -u -r1.9 Makefile.am
--- icons/default/Makefile.am	28 Jun 2002 13:51:01 -0000	1.9
+++ icons/default/Makefile.am	1 Jul 2002 14:27:49 -0000
@@ -31,6 +31,7 @@
 	emblem-nowrite.svg \
 	emblem-ohno.svg \
 	emblem-personal.svg \
+	emblem-shared.svg \
 	emblem-special.svg \
 	emblem-symbolic-link.png \
         emblem-symbolic-link-12.png \
Index: icons/default/emblem-shared.svg
===================================================================
RCS file: icons/default/emblem-shared.svg
diff -N icons/default/emblem-shared.svg
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ icons/default/emblem-shared.svg	1 Jul 2002 14:27:49 -0000
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20000303 Stylable//EN"   "http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/svg-20000303-stylable.dtd"; [
+	<!ENTITY st0 "fill:#4B62AB;stroke:none;">
+	<!ENTITY st1 "fill:#B8BCDB;stroke-linecap:butt;">
+	<!ENTITY st2 "fill:none;stroke:none;">
+	<!ENTITY st3 "fill-rule:nonzero;clip-rule:nonzero;fill:#FFB310;stroke:#000000;stroke-width:0.4236;stroke-linecap:round;stroke-miterlimit:4;">
+]>
+<svg  width="48.168pt" height="48.387pt" viewBox="0 0 48.168 48.387" xml:space="preserve">
+	<g id="Calque_x0020_1" style="&st3;">
+		<path style="&st2;" d="M48.168,48.166H0V0h48.168v48.166z"/>
+		<path style="&st2;" d="M48.117,48.387H0.02V0.29h48.098v48.097z"/>
+		<g>
+			<path d="M5.979,13.698c0-0.584-0.476-1.06-1.059-1.06c-0.587,0-1.062,0.476-1.062,1.06c0,0.013,0.008,0.024,0.008,0.037H3.828v8.785h2.118v-8.668c0.009-0.053,0.032-0.1,0.032-0.154z"/>
+			<path d="M11.408,13.698c0-0.584-0.474-1.06-1.061-1.06c-0.584,0-1.06,0.476-1.06,1.06c0,0.013,0.006,0.024,0.009,0.037H9.281v8.785h2.12v-8.782c0-0.015,0.007-0.026,0.007-0.04z"/>
+			<path style="&st1;" d="M1.239,20.097c-0.091,0.562-0.137,1.146-0.137,1.741c0,4.725,2.948,8.557,6.587,8.557c3.638,0,6.587-3.832,6.587-8.557c0-0.596-0.047-1.18-0.138-1.741H1.239z"/>
+			<path style="&st0;" d="M2.109,21.709c0,0,0.598,9.415,6.501,7.25c5.902-2.169-3.364,1.12-6.501-7.25z"/>
+		</g>
+		<path d="M17.002,40.693c6.469,0.078,5.396,3.521,1.216,7.182h3.306c4.27-4.693,4.519-9.253-4.371-9.606c-10.747-0.426-8.025-8.782-8.025-8.782l-2.272-0.151c0,0-2.422,11.207,10.146,11.358z"/>
+	</g>
+</svg>
Index: libnautilus-private/nautilus-file.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file.c,v
retrieving revision 1.293
diff -u -r1.293 nautilus-file.c
--- libnautilus-private/nautilus-file.c	13 Jun 2002 18:26:13 -0000	1.293
+++ libnautilus-private/nautilus-file.c	1 Jul 2002 14:27:50 -0000
@@ -55,6 +55,7 @@
 #include <pwd.h>
 #include <stdlib.h>
 #include <sys/time.h>
+#include <sys/wait.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -103,6 +104,9 @@
 
 static GHashTable *symbolic_links;
 
+static EelStringList *shared_directories;
+static gboolean can_share_directories;
+
 static char *   nautilus_file_get_owner_as_string            (NautilusFile     *file,
 							      gboolean          include_real_name);
 static char *   nautilus_file_get_type_as_string             (NautilusFile     *file);
@@ -115,6 +119,77 @@
 GNOME_CLASS_BOILERPLATE (NautilusFile, nautilus_file,
 			 GtkObject, GTK_TYPE_OBJECT)
 
+
+static void 
+update_file (const char *string,
+	     gpointer callback_data) {
+
+	NautilusFile *file;
+
+	file = nautilus_file_get_existing (string);
+	if (file != NULL) {
+		nautilus_file_changed (file);
+	}
+	nautilus_file_unref (file);
+}
+
+static int 
+refresh_shared_directories (char * command) {
+	static EelStringList *list;
+	char buffer[4096];
+	FILE *file;
+	int result;
+
+	buffer[0] = '\0';
+
+	list = eel_string_list_new (FALSE);
+	file = popen (command, "r");
+	if (file != NULL) {
+		while (fgets (buffer, sizeof (buffer) - strlen(buffer), file) != NULL) {
+			if (buffer[strlen (buffer) -1] == '\n') {
+				buffer[strlen (buffer) -1] = '\0';
+			}
+			eel_string_list_insert (list, gnome_vfs_get_uri_from_local_path (buffer));
+		}
+		result = pclose (file);
+		if (result == 0) {
+			if (shared_directories != NULL) {
+				g_free (shared_directories);
+			}
+			shared_directories = list;
+		}
+		eel_string_list_for_each (list, update_file, NULL);
+		return result;
+	}
+	return -1;
+}
+
+static void
+fileshare_config_has_changed_callback (NautilusFile *file) {
+	can_share_directories = (geteuid() == 0) 
+		|| refresh_shared_directories (FILESHARE_LIST_PROGRAM " 2> /dev/null") == 0;
+}
+
+static void 
+nautilus_file_initialize_share_monitor() 
+{
+	char *fileshare_uri;
+	NautilusFile *file;
+	GList *attributes;
+	
+	fileshare_uri = gnome_vfs_get_uri_from_local_path (FILESHARE_CONFIG_FILE);
+	file = nautilus_file_get (fileshare_uri);
+	g_free (fileshare_uri);
+	attributes = g_list_prepend (NULL, NAUTILUS_FILE_ATTRIBUTE_METADATA);
+	nautilus_file_monitor_add (file, file, attributes);
+	g_list_free (attributes);
+	g_signal_connect_object (file,
+				 "changed",
+				 G_CALLBACK (fileshare_config_has_changed_callback),
+				 NULL,
+				 0);	
+}
+
 static void
 nautilus_file_instance_init (NautilusFile *file)
 {
@@ -386,6 +461,55 @@
 	return file->details->directory->details->as_file == file;
 }
 
+gboolean
+nautilus_file_can_share_directories (void)
+{
+	return can_share_directories;
+}
+
+gboolean
+nautilus_file_is_shared (NautilusFile *file)
+{
+	char * local_uri;
+	gboolean return_value;
+	if (file != NULL && nautilus_file_is_directory (file) && can_share_directories) {
+		local_uri = nautilus_file_get_uri (file);
+		return_value = eel_string_list_contains (shared_directories, local_uri);
+		g_free (local_uri);
+		return return_value;
+	}
+	else {
+		return FALSE;
+	}
+}
+
+int
+nautilus_file_set_shared (NautilusFile *file, gboolean shared)
+{
+	char *local_uri, *local_path, *option, *command;
+	int result;
+
+	local_uri = nautilus_file_get_uri (file);
+	local_path = gnome_vfs_get_local_path_from_uri (local_uri);
+	if (shared) {
+		option = " --add ";
+	}
+	else {
+		option = " --remove ";
+	}
+	command = g_strconcat (FILESHARE_SET_PROGRAM, option, local_path, " 2>/dev/null", NULL);
+	result = refresh_shared_directories (command);
+
+	nautilus_file_changed (file);
+	g_free (command);
+
+	g_free (local_path);
+	g_free (local_uri);
+	
+	return result;
+}
+
+
 static void
 finalize (GObject *object)
 {
@@ -1609,6 +1733,8 @@
 #if TRASH_IS_FAST_ENOUGH
 	integer |= nautilus_file_is_in_trash (file);
 #endif
+	integer <<= 1;
+	integer |= nautilus_file_is_shared (file);
 
 	return integer;
 }
@@ -1619,6 +1745,11 @@
 {
 	/* Prepend in reverse order. */
 
+	if (nautilus_file_is_shared (file)) {
+		names = g_list_prepend
+			(names, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_SHARED));
+	}
+
 #if TRASH_IS_FAST_ENOUGH
 	if (nautilus_file_is_in_trash (file)) {
 		names = g_list_prepend
@@ -5198,6 +5329,7 @@
 		              NULL, NULL,
 			      g_cclosure_marshal_VOID__VOID,
 		              G_TYPE_NONE, 0);
+	nautilus_file_initialize_share_monitor();
 }
 
 #if !defined (NAUTILUS_OMIT_SELF_CHECK)
Index: libnautilus-private/nautilus-file.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file.h,v
retrieving revision 1.88
diff -u -r1.88 nautilus-file.h
--- libnautilus-private/nautilus-file.h	9 May 2002 19:49:32 -0000	1.88
+++ libnautilus-private/nautilus-file.h	1 Jul 2002 14:27:50 -0000
@@ -71,6 +71,13 @@
 #define NAUTILUS_FILE_EMBLEM_NAME_CANT_READ "noread"
 #define NAUTILUS_FILE_EMBLEM_NAME_CANT_WRITE "nowrite"
 #define NAUTILUS_FILE_EMBLEM_NAME_TRASH "trash"
+#define NAUTILUS_FILE_EMBLEM_NAME_SHARED "shared"
+
+#define FILESHARE_LIST_PROGRAM   NAUTILUS_DATADIR"/filesharelist"
+#define FILESHARE_SET_PROGRAM    NAUTILUS_DATADIR"/fileshareset"
+#define FILESHARE_CONFIG_PROGRAM "/usr/sbin/diskdrake --fileshare"
+#define FILESHARE_CONFIG_FILE    "/etc/security/fileshare.conf"
+
 
 typedef void (*NautilusFileCallback)          (NautilusFile  *file,
 				               gpointer       callback_data);
@@ -143,6 +150,9 @@
 gboolean                nautilus_file_is_directory                      (NautilusFile                   *file);
 gboolean                nautilus_file_is_in_trash                       (NautilusFile                   *file);
 gboolean                nautilus_file_is_in_desktop                     (NautilusFile                   *file);
+gboolean                nautilus_file_can_share_directories             (void);
+int                     nautilus_file_set_shared                        (NautilusFile *file, gboolean shared);
+gboolean                nautilus_file_is_shared                         (NautilusFile                   *file);
 GnomeVFSResult          nautilus_file_get_file_info_result              (NautilusFile                   *file);
 gboolean                nautilus_file_get_directory_item_count          (NautilusFile                   *file,
 									 guint                          *count,
Index: src/file-manager/fm-directory-view.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-directory-view.c,v
retrieving revision 1.541
diff -u -r1.541 fm-directory-view.c
--- src/file-manager/fm-directory-view.c	25 Jun 2002 19:32:12 -0000	1.541
+++ src/file-manager/fm-directory-view.c	1 Jul 2002 14:27:51 -0000
@@ -123,6 +123,8 @@
 #define FM_DIRECTORY_VIEW_COMMAND_CUT_FILES	    			"/commands/Cut Files"
 #define FM_DIRECTORY_VIEW_COMMAND_COPY_FILES				"/commands/Copy Files"
 #define FM_DIRECTORY_VIEW_COMMAND_PASTE_FILES	   			"/commands/Paste Files"
+#define FM_DIRECTORY_VIEW_COMMAND_SHARE                                 "/commands/Share"
+
 
 #define FM_DIRECTORY_VIEW_MENU_PATH_OPEN_ALTERNATE        		"/menu/File/Open Placeholder/OpenAlternate"
 #define FM_DIRECTORY_VIEW_MENU_PATH_OPEN_WITH				"/menu/File/Open Placeholder/Open With"
@@ -303,6 +305,8 @@
 								gpointer              callback_data);
 static void     open_one_properties_window                     (gpointer              data,
 								gpointer              callback_data);
+static void     open_share_properties_window                   (gpointer              data,
+								gpointer              callback_data);
 static void     zoomable_set_zoom_level_callback               (BonoboZoomable       *zoomable,
 								float                 level,
 								FMDirectoryView      *view);
@@ -995,14 +999,22 @@
 {
         FMDirectoryView *view;
         GList *selection;
+	GFunc  open_window;
         
         g_assert (FM_IS_DIRECTORY_VIEW (callback_data));
 
+	if (strcmp("Share",verb) != 0) {
+		open_window = open_one_properties_window;
+	}
+	else {
+		open_window = open_share_properties_window;
+	}
+
         view = FM_DIRECTORY_VIEW (callback_data);
 	selection = fm_directory_view_get_selection (view);
 	if (selection_not_empty_in_menu_callback (view, selection)) {
 		if (fm_directory_view_confirm_multiple_windows (view, g_list_length (selection))) {
-			g_list_foreach (selection, open_one_properties_window, view);
+			g_list_foreach (selection, open_window, view);
 		}
 	}
 
@@ -3276,6 +3288,15 @@
 }
 
 static void
+open_share_properties_window (gpointer data, gpointer callback_data)
+{
+	g_assert (NAUTILUS_IS_FILE (data));
+	g_assert (FM_IS_DIRECTORY_VIEW (callback_data));
+
+	fm_properties_window_show_share (data, callback_data);
+}
+
+static void
 remove_custom_icon (gpointer file, gpointer callback_data)
 {
 	g_assert (NAUTILUS_IS_FILE (file));
@@ -4251,6 +4272,7 @@
 		BONOBO_UI_VERB ("Reset Background", reset_background_callback),
 		BONOBO_UI_VERB ("Reset to Defaults", reset_to_defaults_callback),
 		BONOBO_UI_VERB ("Select All", bonobo_menu_select_all_callback),
+		BONOBO_UI_VERB ("Share", open_properties_window_callback),
 		BONOBO_UI_VERB ("Properties", open_properties_window_callback),
 		BONOBO_UI_VERB ("Show Trash", show_trash_callback),
 		BONOBO_UI_VERB ("Trash", trash_callback),
@@ -4264,7 +4286,6 @@
 	eel_add_weak_pointer (&view->details->ui);
 
 	bonobo_ui_component_add_verb_list_with_data (view->details->ui, verbs, view);
-
 	g_signal_connect_object (fm_directory_view_get_background (view), "settings_changed",
 				 G_CALLBACK (schedule_update_menus), G_OBJECT (view),
 				 G_CONNECT_SWAPPED);
@@ -4323,9 +4344,12 @@
 	gboolean can_copy_files;
 	gboolean can_link_files;
 	gboolean can_duplicate_files;
+	gboolean can_show_share;
 	gboolean show_separate_delete_command;
 	gboolean vfolder_directory;
 	EelBackground *background;
+	char* directory_uri_string;
+	GnomeVFSURI *directory_uri, *home_uri;
 
 	if (view->details->ui == NULL) {
 		return;
@@ -4347,7 +4371,17 @@
 	can_link_files = can_create_files && can_copy_files;
 	
 	vfolder_directory = we_are_in_vfolder_desktop_dir (view);
-
+	if (nautilus_file_can_share_directories() && (selection_count == 1)) {
+		directory_uri_string = nautilus_file_get_uri (NAUTILUS_FILE (selection->data));
+		directory_uri = gnome_vfs_uri_new (directory_uri_string);
+		home_uri = gnome_vfs_uri_new (gnome_vfs_get_uri_from_local_path (g_get_home_dir ()));
+		can_show_share = nautilus_file_is_directory (NAUTILUS_FILE (selection->data)) 
+			&& (gnome_vfs_uri_equal (home_uri, directory_uri) || gnome_vfs_uri_is_parent (home_uri, directory_uri, TRUE));
+	}
+	else {
+		can_show_share = FALSE;
+	}
+ 
 	bonobo_ui_component_freeze (view->details->ui, NULL);
 
 	nautilus_bonobo_set_sensitive (view->details->ui, 
@@ -4542,6 +4576,10 @@
 				       FM_DIRECTORY_VIEW_COMMAND_EDIT_LAUNCHER,
 				       selection_count == 1);
 
+	nautilus_bonobo_set_hidden (view->details->ui,
+				    FM_DIRECTORY_VIEW_COMMAND_SHARE,
+				    geteuid () != 0 && !can_show_share);
+ 
 	bonobo_ui_component_thaw (view->details->ui, NULL);
 
 	nautilus_file_list_free (selection);
Index: src/file-manager/fm-properties-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-properties-window.c,v
retrieving revision 1.153
diff -u -r1.153 fm-properties-window.c
--- src/file-manager/fm-properties-window.c	17 May 2002 19:58:13 -0000	1.153
+++ src/file-manager/fm-properties-window.c	1 Jul 2002 14:27:51 -0000
@@ -32,6 +32,7 @@
 #include <eel/eel-gnome-extensions.h>
 #include <eel/eel-gtk-extensions.h>
 #include <eel/eel-labeled-image.h>
+#include <eel/eel-radio-button-group.h>
 #include <eel/eel-stock-dialogs.h>
 #include <eel/eel-string.h>
 #include <eel/eel-vfs-extensions.h>
@@ -69,9 +70,11 @@
 #include <libnautilus-private/nautilus-undo-signal-handlers.h>
 #include <libnautilus/nautilus-undo.h>
 #include <string.h>
+#include <pthread.h>
 
 static GHashTable *windows;
 static GHashTable *pending_files;
+static pthread_t   fileshare_thread = (pthread_t) NULL;
 
 struct FMPropertiesWindowDetails {
 	NautilusFile *original_file;
@@ -99,6 +102,8 @@
 	int num_special_flags_rows;
 
 	gboolean deep_count_finished;
+
+	GtkNotebook *share_notebook;
 };
 
 enum {
@@ -126,6 +131,7 @@
 	NautilusFile *original_file;
 	NautilusFile *target_file;
 	FMDirectoryView *directory_view;
+	gboolean      show_share;
 } StartupData;
 
 
@@ -165,6 +171,8 @@
 						   gboolean                 cancel_call_when_ready,
 						   gboolean                 cancel_timed_wait,
 						   gboolean                 cancel_destroy_handler);
+static void real_fm_properties_window_present     (NautilusFile *original_file, 
+						   FMDirectoryView *directory_view, gboolean show_share);
 
 GNOME_CLASS_BOILERPLATE (FMPropertiesWindow, fm_properties_window,
 			 GtkWindow, GTK_TYPE_WINDOW)
@@ -1504,6 +1512,16 @@
 }
 
 static gboolean
+should_show_share (FMPropertiesWindow *window) 
+{
+	if (nautilus_file_is_directory (window->details->target_file)) {
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
 should_show_link_target (FMPropertiesWindow *window)
 {
 	if (nautilus_file_is_symbolic_link (window->details->target_file)) {
@@ -2141,6 +2159,7 @@
 	data->original_file = nautilus_file_ref (original_file);
 	data->target_file = nautilus_file_ref (target_file);
 	data->directory_view = directory_view;
+	data->show_share = FALSE;
 
 	return data;
 }
@@ -2153,6 +2172,202 @@
 	g_free (data);
 }
 
+static void
+update_share_tab (FMPropertiesWindow *window) {
+	GnomeVFSURI *directory_uri, *home_uri;
+	char *directory_uri_string;
+	NautilusFile *file;
+	gint page_number;
+
+	file = window->details->target_file;
+
+	g_return_if_fail (nautilus_file_is_directory(file) == TRUE);
+
+	directory_uri_string = nautilus_file_get_uri (file);
+	directory_uri = gnome_vfs_uri_new (directory_uri_string);
+	home_uri = gnome_vfs_uri_new (gnome_vfs_get_uri_from_local_path (g_get_home_dir ()));
+
+	if (gnome_vfs_uri_equal (home_uri, directory_uri)
+	    || gnome_vfs_uri_is_parent (home_uri, directory_uri, TRUE)) {
+		if (g_file_test(FILESHARE_LIST_PROGRAM,G_FILE_TEST_EXISTS)) {
+			if (nautilus_file_can_share_directories()) {
+				page_number = 0;
+			}
+			else {
+				page_number = 1;
+			}
+		}
+		else {
+			page_number = 2;
+		}
+	}
+	else {
+		page_number = 3;
+	}
+
+	gtk_widget_set_sensitive(gtk_notebook_get_nth_page(window->details->share_notebook, 
+							   gtk_notebook_get_current_page(window->details->share_notebook)), 
+				 (fileshare_thread == (pthread_t) NULL));
+	gtk_notebook_set_current_page(window->details->share_notebook, page_number);
+
+	gnome_vfs_uri_unref (directory_uri);
+	gnome_vfs_uri_unref (home_uri);	
+	g_free (directory_uri_string);
+}
+
+static void
+update_share_property (gpointer key, gpointer value, gpointer user_data) {
+	g_return_if_fail (FM_IS_PROPERTIES_WINDOW (value));
+	update_share_tab(value);
+}
+
+static void *
+fileshare_config_exec (void *arg)
+{
+		
+	system(FILESHARE_CONFIG_PROGRAM);
+
+	eel_g_hash_table_safe_for_each (windows, update_share_property, NULL);
+
+	fileshare_thread = (pthread_t) NULL;
+	pthread_exit (NULL);
+
+	/* compilation on Solaris warns of no return 
+	   value on non-void function...so....*/
+	return (void *) 0;
+}
+
+static void disable_share_property (gpointer key, gpointer value, gpointer user_data) {
+	FMPropertiesWindow *window;
+
+	g_return_if_fail (FM_IS_PROPERTIES_WINDOW (value));
+	window = FM_PROPERTIES_WINDOW (value);
+	gtk_widget_set_sensitive(gtk_notebook_get_nth_page(window->details->share_notebook, 
+							   gtk_notebook_get_current_page(window->details->share_notebook)), 
+				 FALSE);
+}
+
+static void launch_filesharing_callback (GtkWidget               *widget,
+					 GtkNotebook             *share_notebook) 
+{
+	eel_g_hash_table_safe_for_each (windows, disable_share_property, NULL);
+
+	pthread_create (&fileshare_thread, NULL, fileshare_config_exec, NULL );
+}
+
+static void
+share_changed (EelRadioButtonGroup *radio_buttons, NautilusFile * file) {
+	int selected;
+
+	g_assert (EEL_IS_RADIO_BUTTON_GROUP (radio_buttons));
+	g_assert (NAUTILUS_IS_FILE (file));
+
+	selected = eel_radio_button_group_get_active_index (radio_buttons);
+	if (g_object_get_data (G_OBJECT(radio_buttons),"sharing_in_progress") == NULL) {
+		int result;
+		result = nautilus_file_set_shared (file, selected);
+		if (result != 0) {
+			g_object_set_data (G_OBJECT (radio_buttons), "sharing_in_progress", "true");
+			eel_radio_button_group_set_active_index (radio_buttons, !selected);			
+			g_object_set_data(G_OBJECT (radio_buttons), "sharing_in_progress", NULL);
+
+			eel_show_error_dialog (_("Error while running " FILESHARE_SET_PROGRAM),
+					       _("Error while running " FILESHARE_SET_PROGRAM),
+						 GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (radio_buttons))));
+		}
+	}
+	
+}
+
+
+/* Share properties */
+static GtkWidget *
+create_share_page (FMPropertiesWindow *window)
+{
+	GtkWidget *vbox, *filesharing_button, *share_radio_buttons;
+	GtkWidget *notebook;
+	NautilusFile *file;
+
+	file = window->details->target_file;
+
+	g_return_val_if_fail (nautilus_file_is_directory(file) == TRUE, NULL);
+
+	notebook = gtk_notebook_new ();
+	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
+
+	gtk_widget_show (notebook);
+
+	gtk_notebook_append_page (window->details->notebook, notebook, gtk_label_new (dgettext("gtk+mdk", "Share")));
+
+	
+	/* create general sharing page */
+	vbox = create_page_with_vbox (GTK_NOTEBOOK (notebook), "shared authorized");
+
+	share_radio_buttons = eel_radio_button_group_new (FALSE);
+	gtk_box_pack_start (GTK_BOX (vbox), share_radio_buttons, FALSE, FALSE, 0);
+
+	eel_radio_button_group_insert (EEL_RADIO_BUTTON_GROUP (share_radio_buttons), 
+				       dgettext("gtk+mdk","Not shared"));
+	eel_radio_button_group_insert (EEL_RADIO_BUTTON_GROUP (share_radio_buttons), 
+				       dgettext("gtk+mdk","Shared"));	
+	eel_radio_button_group_set_active_index (EEL_RADIO_BUTTON_GROUP (share_radio_buttons), 
+						 nautilus_file_is_shared(file));
+				
+	g_signal_connect (share_radio_buttons,
+			  "changed",
+			  G_CALLBACK (share_changed),
+			  file);
+								  
+	gtk_widget_show (share_radio_buttons);
+
+	add_prompt (GTK_VBOX (vbox), 
+		    dgettext("gtk+mdk",
+			     "Sharing this directory makes it available under\nLinux/Unix (NFS) and Windows (Samba)"),
+		    TRUE);
+	filesharing_button = gtk_button_new_with_label (dgettext("gtk+mdk","Configure File Sharing"));
+	gtk_widget_show (filesharing_button);
+	gtk_box_pack_end (GTK_BOX (vbox), filesharing_button, FALSE, FALSE, 4);  
+	add_prompt_and_separator ( GTK_VBOX (vbox), dgettext("gtk+mdk",
+							     "You can also reconfigure file sharing authorisation"));
+	g_signal_connect(filesharing_button, "clicked", 
+			 G_CALLBACK (launch_filesharing_callback), notebook);
+	gtk_notebook_reorder_child (GTK_NOTEBOOK (notebook), vbox, 0);
+
+	
+	/* create "not configured" sharing page */
+	vbox = create_page_with_vbox (GTK_NOTEBOOK (notebook), "shared not configured");
+	filesharing_button = gtk_button_new_with_label (dgettext("gtk+mdk","Configure File Sharing"));
+	gtk_widget_show (filesharing_button);
+	gtk_box_pack_start (GTK_BOX (vbox), filesharing_button, FALSE, FALSE, 4);  
+	g_signal_connect(filesharing_button, "clicked", 
+			 G_CALLBACK (launch_filesharing_callback), notebook);
+	
+	add_prompt_and_separator ( GTK_VBOX (vbox), dgettext("gtk+mdk",
+							     "You need to be authorized to share directories"));
+	gtk_notebook_reorder_child (GTK_NOTEBOOK (notebook), vbox, 1);
+				
+	/* create "error" sharing page */
+	vbox = create_page_with_vbox (GTK_NOTEBOOK (notebook), "shared error");
+
+	add_prompt ( GTK_VBOX (vbox), dgettext("gtk+mdk", 
+					       "Error running `filesharelist'. Check if installed and in\n$PATH or /usr/sbin."), TRUE);
+	gtk_notebook_reorder_child (GTK_NOTEBOOK (notebook), vbox, 2);
+
+	/* create "home only" sharing page */
+	vbox = create_page_with_vbox (GTK_NOTEBOOK (notebook), "home only");
+
+	add_prompt ( GTK_VBOX (vbox), dgettext("gtk+mdk","Only directories in your Home can be shared."), TRUE);
+	gtk_notebook_reorder_child (GTK_NOTEBOOK (notebook), vbox, 3);
+
+	window->details->share_notebook = GTK_NOTEBOOK (notebook);
+	
+	update_share_tab(window);	
+	
+	return notebook;
+}
+
+
+
 static FMPropertiesWindow *
 create_properties_window (StartupData *startup_data)
 {
@@ -2221,6 +2436,21 @@
 	if (should_show_permissions (window)) {
 		create_permissions_page (window);
 	}
+
+	if (should_show_share (window)) {
+		create_share_page (window);
+
+		if (startup_data->show_share) {
+			gtk_notebook_set_current_page (window->details->notebook, 
+						       gtk_notebook_page_num (window->details->notebook, 
+									      GTK_WIDGET (window->details->share_notebook)));
+		}
+	}
+	else {
+		window->details->share_notebook = NULL;
+	}
+
+
 	
 	/* Create box for close button. */
 	hbox = gtk_hbutton_box_new ();
@@ -2347,8 +2577,20 @@
 }
 
 void
+fm_properties_window_show_share (NautilusFile *original_file, FMDirectoryView *directory_view)
+{
+	real_fm_properties_window_present (original_file, directory_view, TRUE);
+}
+
+void
 fm_properties_window_present (NautilusFile *original_file, FMDirectoryView *directory_view)
 {
+	real_fm_properties_window_present (original_file, directory_view, FALSE);
+}
+
+void
+real_fm_properties_window_present (NautilusFile *original_file, FMDirectoryView *directory_view, gboolean show_share)
+{
 	GtkWindow *existing_window;
 	GtkWidget *parent_window;
 	NautilusFile *target_file;
@@ -2383,6 +2625,7 @@
 
 	target_file = get_target_file (original_file);
 	startup_data = startup_data_new (original_file, target_file, directory_view);
+	startup_data->show_share = show_share;
 	nautilus_file_unref (target_file);
 
 	/* Wait until we can tell whether it's a directory before showing, since
Index: src/file-manager/fm-properties-window.h
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-properties-window.h,v
retrieving revision 1.7
diff -u -r1.7 fm-properties-window.h
--- src/file-manager/fm-properties-window.h	15 Sep 2001 19:18:15 -0000	1.7
+++ src/file-manager/fm-properties-window.h	1 Jul 2002 14:27:51 -0000
@@ -62,5 +62,7 @@
 GtkType fm_properties_window_get_type   (void);
 void 	fm_properties_window_present 	(NautilusFile    *file, 
 					 FMDirectoryView *directory_view);
+void    fm_properties_window_show_share (NautilusFile    *file,
+					 FMDirectoryView *directory_view);
 
 #endif /* FM_PROPERTIES_WINDOW_H */
Index: src/file-manager/nautilus-directory-view-ui.xml
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/nautilus-directory-view-ui.xml,v
retrieving revision 1.44
diff -u -r1.44 nautilus-directory-view-ui.xml
--- src/file-manager/nautilus-directory-view-ui.xml	30 May 2002 17:57:00 -0000	1.44
+++ src/file-manager/nautilus-directory-view-ui.xml	1 Jul 2002 14:27:51 -0000
@@ -69,6 +69,9 @@
 	<cmd name="Trash"
          _label="Move to Trash"
 	 _tip="Move each selected item to the Trash"/>
+        <cmd name="Share"
+         _label="Share"
+         _tip="Share Directory"/>
 </commands>
 <keybindings>
 	<accel name="*Control*BackSpace" verb="Trash"/>
@@ -136,6 +139,10 @@
 			<menuitem name="Duplicate"
 				  _label="_Duplicate"
 				  verb="Duplicate"/>
+                        <menuitem name="Share"
+				  _label="_Share"
+				  accel="*Control*s"
+				  verb="Share"/>
 			<menuitem name="Create Link"
 				  _label="_Make Link"
 				  accel="*Control*m"
@@ -271,6 +278,7 @@
 		</placeholder>
 		<placeholder name="File Actions" delimit="top">
 			<menuitem name="Properties" verb="Properties"/>
+                        <menuitem name="Share" verb="Share"/>
 			<menuitem name="Duplicate" verb="Duplicate"/>
 			<menuitem name="Create Link" verb="Create Link"/>
 			<menuitem name="Rename" verb="Rename"/>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]