# file-lib.pl
# Common functions for file manager CGIs

do '../web-lib.pl';
&ReadParse(\%prein, 'GET');
if ($prein{'trust'}) {
	&open_trust_db();
	if ($trustdb{$prein{'trust'}}) {
		$trust_unknown_referers = 1;
		$trustdb{$prein{'trust'}} = time();
		}
	dbmclose(%trustdb);
	}
&init_config();
%access = &get_module_acl();
if ($access{'home'}) {
	local @u = getpwnam($remote_user);
	$u[7] = &resolve_links($u[7]);
	if (@u) {
		$access{'root'} .= ' ' if ($access{'root'});
		$access{'root'} .= $u[7];
		}
	}

$icon_map = (	"c", 1,    "txt", 1,
		"pl", 1,   "cgi", 1,
		"html", 1, "htm", 1,
		"gif", 2,  "jpg", 2,
		"tar", 3
		);

# file_info_line(path)
# Returns a line of text containing encoded details of some file
sub file_info_line
{
local @st = $access{'follow'} ? stat($_[0]) : lstat($_[0]);
local $ext = $_[0] =~ /\S+\.([^\.\/]+)$/ ? $1 : undef;
if (!@st) {
	# Work around a broken stat function on large files on redhat 7.x
	&has_command("stat") || return undef;
	local $out = `stat -t '$_[0]'`;
	return undef if ($?);
	$out =~ /^(.*)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
	local $type = defined($icon_map{$ext}) ? $icon_map{$ext} : 4;
	local $user = getpwuid($5);
	$user = $5 if (!$user);
	local $group = getgrgid($6);
	$group = $6 if (!$group);
	local $size = $2;
	local $mtime = $13;
	local $mode = hex($4);
	return sprintf ("%s\t%u\t%s\t%s\t%u\t%u\t%u\t%s",
		$_[0], $type, $user, $group, $size, $mode, $mtime, undef);
	}
local $type = !$access{'follow'} && -l $_[0] ? 5 :
	      -d _ ? 0 :
	      -b _ ? 6 :
	      -c _ ? 6 :
	      -p _ ? 7 :
	      -S _ ? 7 : defined($icon_map{$ext}) ? $icon_map{$ext} : 4;
local $user = getpwuid($st[4]);
$user = $st[4] if (!$user);
local $group = getgrgid($st[5]);
$group = $st[5] if (!$group);
local $rl = readlink($_[0]);
return sprintf ("%s\t%u\t%s\t%s\t%u\t%u\t%u\t%s",
		$_[0], $type,
		$user, $group,
		$st[7], $st[2], $st[9], $access{'follow'} ? "" :
					-l _ && !$rl ? "???" : $rl);
}

# switch_acl_uid()
sub switch_acl_uid
{
if ($access{'uid'}) {
	local @u = $access{'uid'} < 0 ? getpwnam($remote_user)
				      : getpwuid($access{'uid'});
	@u || &error($text{'switch_euser'});
	$( = $u[3]; $) = "$u[3] ".join(" ", $u[3], &other_groups($u[0]));
	($>, $<) = ($u[2], $u[2]);
	umask(oct($access{'umask'}));
	}
}

# can_access(file)
sub can_access
{
local @f = grep { $_ ne '' } split(/\//, $_[0]);
DIR: foreach $r (split(/\s+/, $access{'root'})) {
	return 1 if ($r eq '/' || $_[0] eq '/');
	local @a = grep { $_ ne '' } split(/\//, $r);
	local $i;
	for($i=0; $i<@a && $i<@f; $i++) {
		next DIR if ($a[$i] ne $f[$i]);
		}
	return 1;
	}
return 0;
}

# accessible_subdir(dir)
# Returns the path to a dir under the given one that we can access
sub accessible_subdir
{
local ($r, @rv);
foreach $r (split(/\s+/, $access{'root'})) {
	if ($r =~ /^(\Q$_[0]\E\/[^\/]+)/) {
		push(@rv, $1);
		}
	}
return @rv;
}

sub open_trust_db
{
local $trust = "$ENV{'WEBMIN_CONFIG'}/file/trust";
eval "use SDBM_File";
dbmopen(%trustdb, $trust, 0700);
eval { $trustdb{'1111111111'} = 'foo bar' };
if ($@) {
	dbmclose(%trustdb);
	eval "use NDBM_File";
	dbmopen(%trustdb, $trust, 0700);
	}
}

1;

