diff options
Diffstat (limited to '')
| -rwxr-xr-x | Bonus/smb.cgi | 462 | 
1 files changed, 462 insertions, 0 deletions
| diff --git a/Bonus/smb.cgi b/Bonus/smb.cgi new file mode 100755 index 0000000..536db89 --- /dev/null +++ b/Bonus/smb.cgi @@ -0,0 +1,462 @@ +#!/usr/bin/perl + +# Workgroup list: file:/$LIB/smb.cgi +# Server list:    file:/$LIB/smb.cgi?workgroup +# Sahre list:     file:/$LIB/smb.cgi?//server +#                 file:/$LIB/smb.cgi/server +# Directory:      file:/$LIB/smb.cgi?//server/share +#                 file:/$LIB/smb.cgi?//server/share/dir... +#                 file:/$LIB/smb.cgi/server/share +# Get file:       file:/$LIB/smb.cgi?//server/share/dir.../file +#                 file:/$LIB/smb.cgi/server/share/dir.../file +# +# ----- ~/.w3m/smb ----- +# workgroup = <workgroup> +# [ username = <username> ] +# [ password = <password> ] +# [ password_file = <password_file> ] +# ---------------------- +# --- <password_file> --- +# <password> +# ----------------------- +# default: +#  <username> = $USER +#  <password> = $PASSWD  (Don't use!) +#  <password_file> = $PASSWD_FILE + +$DEBUG = 1; + +$MIME_TYPE = "~/.mime.types"; +$AUTH_FILE = "~/.w3m/smb"; +$MIME_TYPE =~ s@^~/@$ENV{"HOME"}/@; +$AUTH_FILE =~ s@^~/@$ENV{"HOME"}/@; +$WORKGROUP = "-"; +$USER = $ENV{"USER"}; +$PASSWD = $ENV{"PASSWD"}; +$PASSWD_FILE = $ENV{"PASSWD_FILE"}; +&load_auth_file($AUTH_FILE); + +$NMBLOOKUP = "nmblookup"; +$SMBCLIENT = "smbclient"; +@NMBLOOKUP_OPT = ("-T"); +@SMBCLIENT_OPT = ("-N"); +$USE_OPT_A = defined($PASSWD) && (-f $AUTH_FILE) && &check_opt_a(); +if ($USE_OPT_A) { +	push(@SMBCLIENT_OPT, "-A", $AUTH_FILE); +} elsif (-f $PASSWD_FILE) { +	$USE_PASSWD_FILE = 1; +} elsif (defined($PASSWD)) { +	$USE_PASSWD_FD = 1; +	$PASSWD_FD = 0; +} +if (defined($PASSWD)) { +	$passwd = "*" x 8; +} +$DEBUG && print <<EOF; +DEBUG: NMBLOOKUP=$NMBLOOKUP @NMBLOOKUP_OPT +DEBUG: SMBCLIENT=$SMBCLIENT @SMBCLIENT_OPT +DEBUG: WORKGROUP=$WORKGROUP +DEBUG: USER=$USER +DEBUG: PASSWD=$passwd +DEBUG: PASSWD_FILE=$PASSWD_FILE +DEBUG: PASSWD_FD=$PASSWD_FD +EOF + +$PAGER = "cat"; +$FILE = "F000"; + +$CGI = "file://" . &file_encode($ENV{"SCRIPT_NAME"} || $0); +$QUERY = $ENV{"QUERY_STRING"}; +$PATH_INFO = $ENV{"PATH_INFO"}; + +if ($PATH_INFO =~ m@^/@) { +	$_ = $PATH_INFO; +	if (! m@^//@) { +		$_ = "/$_"; +	} +	s@[\r\n\0\\"]@@g; +	$DEBUG && print "DEBUG: PATH_INFO=\"$_\"\n"; +	$Q = ""; +} +else { +	$_ = &file_decode($QUERY); +	$DEBUG && print "DEBUG: QUERY_STRING=\"$_\"\n"; +	$Q = "?"; +} +if (s@^//([^/]+)@@) { +	$server = $1; +#	if (!$USE_OPT_A && !defined($PASSWD)) { +#		&print_form("//$server$_"); +#		exit; +#	} +	if (s@^/([^/]+)@@) { +		&file_list("//$server/$1", &cleanup($_)); +	} else { +		&share_list($server); +	} +} elsif (m@^[^/]@) { +	&server_list($_); +} else { +	&group_list(); +} + +sub file_list { +	local($service, $file) = @_; +	local(@files) = (); +	local($dir, $qservice, $qfile);  +	local($_, $c); + +$DEBUG && print "DEBUG: service=\"$service\" file=\"$file\"\n"; +	if ($file eq "/") { +		goto get_list; +	} +	$_ = $file; +	s@/@\\@g; +	@cmd = ($SMBCLIENT, $service, @SMBCLIENT_OPT, "-c", "ls \"$_\""); +	$F = &open_pipe(1, @cmd); +	while (<$F>) { +$DEBUG && print "DEBUG: $_"; +		/^\s/ && last; +	} +	close($F); +	if (s/\s+([A-Z]*) {1,8}\d+  (\w{3} ){2}[ \d]\d \d\d:\d\d:\d\d \d{4}\s*$// +		&& $1 !~ /D/) { +		&get_file($service, $file); +		exit; +	} + +    get_list: +	$_ = "$file/*"; +	s@/+@\\@g; +	@cmd = ($SMBCLIENT, $service, @SMBCLIENT_OPT, "-c", "ls \"$_\""); +	$F = &open_pipe(1, @cmd); +	while (<$F>) { +		/^\s*$/ && last; +$DEBUG && print "DEBUG: $_"; +		/^cd\s+/ && last; +		/^\S/ && next; +		s/\r?\n//; +		push(@files, $_); +	} +	close($F); + +	$qservice = &html_quote($service); +	$service = &file_encode($service); +	$qfile = &html_quote($file); +	$file = &file_encode($file); + +	print "Content-Type: text/html\n\n"; +	print "<title>$qservice$qfile</title>\n"; +	print "<b>$qservice$qfile</b>\n"; +	print "<pre>\n"; +	for (sort @files) { +		s/\s+([A-Z]*) {1,8}\d+  (\w{3} ){2}[ \d]\d \d\d:\d\d:\d\d \d{4}\s*$// || next; +		$c = $&; +		s/^  //; +		$_ eq "." && next; +		print "<a href=\"$CGI$Q$service" +			. &cleanup("$file/" . &file_encode($_)) . "\">" +			. &html_quote($_) . "</a>" +			. &html_quote($c) . "\n"; +	} +	print "</pre>\n"; +} + +sub get_file { +	local($service, $file) = @_; +	local($encoding, $type); +	local($_, @cmd); + +	$_ = $file; +	s@/@\\@g; +	@cmd = ($SMBCLIENT, $service, @SMBCLIENT_OPT, "-E", "-c", "more \"$_\""); +$DEBUG && print "DEBUG: @cmd\n"; + +	($encoding, $type) = &guess_type($file); +	$file =~ s@^.*/@@; +	$| = 1; +	print "Content-Encoding: $encoding\n" if $encoding; +	print "Content-Type: $type; name=\"$file\"\n\n"; + +	$ENV{"PAGER"} = $PAGER if $PAGER; +	&exec_cmd(1, @cmd); +} + +sub share_list { +	local($server) = @_; +	local(@share); +	local($qserver, $_, $d, @c); + +	@share = &get_list(1, $server, "Share"); + +	$qserver = &html_quote($server); +	$server = &file_encode($server); + +	print "Content-Type: text/html\n\n"; +	print "<title>Share list: $qserver</title>\n"; +	print "<table>\n"; +	print "<tr><td colspan=3><b>$qserver</b>"; +	for (sort @share) { +		($_, $d, @c) = split(" "); +		if ($d eq 'Disk') { +			print "<tr><td>+ <a href=\"$CGI$Q//$server/" +				. &file_encode($_) . "\">" +				. &html_quote($_) . "</a>"; +		} else { +			print "<tr><td>+ " +				. &html_quote($_); +		} +		print "<td><td>" +			. &html_quote($d) . "<td><td>" +			. &html_quote("@c") . "\n"; +	} +	print "</table>\n"; +} + +sub server_list { +	local($group) = @_; +	local($master, @server); +	local($_, @c); + +	$master = &get_master($group); +	@server = &get_list(0, $master, "Server"); + +	$group = &html_quote($group); + +	print "Content-Type: text/html\n\n"; +	print "<title>Server list: $group</title>\n"; +	print "<table>\n"; +	print "<tr><td colspan=3><b>$group</b>\n"; +	for (sort @server) { +		($_, @c) = split(" "); +		print "<tr><td>+ <a href=\"$CGI$Q//" +			. &file_encode($_) . "\">" +			. &html_quote($_) . "</a><td><td>" +			. &html_quote("@c") . "\n"; +	} +	print "</table>\n"; +} + +sub group_list { +	local($master, @group); +	local($_, @c); + +	$master = &get_master($WORKGROUP || "-"); +	@group = &get_list(0, $master, "Workgroup"); + +	print "Content-Type: text/html\n\n"; +	print "<title>Workgroup list</title>\n"; +	print "<table>\n"; +	for (sort @group) { +		($_, @c) = split(" "); +		print "<tr><td><a href=\"$CGI?" +			. &file_encode($_) . "\">" +			. &html_quote($_) . "</a><td><td>" +			. &html_quote("@c") . "\n"; +	} +	print "</table>\n"; +} + +sub check_opt_a { +	local($_, $F, @cmd); + +	@cmd = ($SMBCLIENT, "-h"); +	$F = &open_pipe(0, @cmd); +	while (<$F>) { +		if (/^\s*-A\s/) { +$DEBUG && print "DEBUG: $_"; +			close($F); +			return 1; +		} +	} +	close($F); +	return 0; +} + +sub get_master { +	local($group) = @_; +	local($_, $F, @cmd); + +	@cmd = ($NMBLOOKUP, "-M", @NMBLOOKUP_OPT, $group); +	$F = &open_pipe(0, @cmd); +	$_ = <$F>; +	$_ = <$F>; +	close($F); +	($_) = split(/[,\s]/); +	s/\.*$//; +	return $_; +} + +sub get_list { +	local($passwd, $server, $header) = @_; +	local(@list) = (); +	local($_, @cmd, $F); + +	@cmd = ($SMBCLIENT, @SMBCLIENT_OPT, "-L", $server); +	$F = &open_pipe($passwd, @cmd); +	while (<$F>) { +		if (/^\s*$header/) { +$DEBUG && print "DEBUG: $_"; +			last; +		} +	} +	while (<$F>) { +		/^\s*$/ && last; +$DEBUG && print "DEBUG: $_"; +		/^\S/ && last; +		/^\s*-/ && next; +		push(@list, $_); +	} +	close($F); +	return @list; +} + +sub open_pipe { +	local($passwd, @cmd) = @_; +	local($F) = $FILE++; + +$DEBUG && print "DEBUG: @cmd\n"; +	open($F, "-|") || &exec_cmd($passwd, @cmd); +	return $F; +} + +sub exec_cmd { +	local($passwd, @cmd) = @_; + +	$ENV{"LC_ALL"} = "C"; +	$ENV{"USER"} = $USER; +	if ($passwd && !$USE_OPT_A) { +		if ($USE_PASSWD_FILE) { +			$ENV{"PASSWD_FILE"} = $PASSWD_FILE; +		} elsif ($USE_PASSWD_FD) { +			$ENV{"PASSWD_FD"} = $PASSWD_FD; +			if (open(W, "|-")) { +				print W $PASSWD; +				close(W); +				exit; +			} +		} +	} +	open(STDERR, ">/dev/null"); +	exec @cmd; +	exit 1; +} + +sub print_form { +	local($_) = @_; +	local($q) = &html_quote($_); +	$_ = &file_encode($_); + +	print <<EOF; +Content-Type: text/html + +<h1>$q</h1> +<form action="$CGI$Q$_" method=POST> +<table> +<tr><td>Workgroup	<td>User	<td>Password +<tr><td><input type=text size=8 name=group value="$WORKGROUP"> +    <td><input type=text size=8 name=user value="$USER"> +    <td><input type=password size=8 name=passwd value="$PASSWD"> +    <td><input type=submit name=OK value=OK> +</table> +</form> +EOF +} + +sub load_auth_file { +	local($_) = @_; + +	if ($USER =~ s/%(.*)$//) { +		$PASSWD = $1 unless $PASSWD; +	} +	open(F, $_) || return; +	while (<F>) { +		s/\s+$//; +		if (s/^workgroup\s*=\s*//i) { +			$WORKGROUP = $_; +		} elsif (s/^user(name)?\s*=\s*//i) { +			$USER = $_; +		} elsif (s/^passw(or)?d\s*=\s*//i) { +			$PASSWD = $_; +		} elsif (s/^passw(or)?d_file\s*=\s*//i) { +			$PASSWD_FILE = $_; +		} +	} +	close(F); +} + +sub load_mime_type { +	local($_) = @_; +	local(%mime) = (); +	local($type, @suffix); + +	open(F, $_) || return (); +	while(<F>) { +		/^#/ && next; +		chop; +		(($type, @suffix) = split(" ")) >= 2 || next; +		for (@suffix) { +			$mime{$_} = $type; +		} +	} +	close(F); +	return %mime; +} + +sub guess_type { +	local($_) = @_; +	local(%mime) = &load_mime_type($MIME_TYPE); +	local($encoding) = undef; + +	if (s/\.gz$//i) { +		$encoding = "gzip"; +	} elsif (s/\.Z$//i) { +		$encoding = "compress"; +	} elsif (s/\.bz2?$//i) { +		$encoding = "bzip2"; +	} +	/\.(\w+)$/; +	$_ = $1; +	tr/A-Z/a-z/; +	return ($encoding, $mime{$_} || "text/plain"); +} + +sub cleanup { +	local($_) = @_; + +	$_ .= "/"; +	s@//+@/@g; +	s@/\./@/@g; +	while(m@/\.\./@) { +		s@^/(\.\./)+@/@; +		s@/[^/]+/\.\./@/@; +	} +	s@(.)/$@$1@; +	return $_; +} + +sub file_encode { +	local($_) = @_; +	s/[\000-\040\+:#?&%<>"\177-\377]/sprintf('%%%02X', unpack('C', $&))/eg; +	return $_; +} + +sub file_decode { +	local($_) = @_; +	s/\+/ /g; +	s/%([\da-f][\da-f])/pack('C', hex($1))/egi; +	s@[\r\n\0\\"]@@g; +	return $_; +} + +sub html_quote { +	local($_) = @_; +	local(%QUOTE) = ( +		'<', '<', +		'>', '>', +		'&', '&', +		'"', '"', +	); +	s/[<>&"]/$QUOTE{$&}/g; +	return $_; +} | 
