#!/usr/bin/perl # Workgroup list: file:/$LIB/smb.cgi # Server list: file:/$LIB/smb.cgi?workgroup # Sahre list: file:/$LIB/smb.cgi?//server # Directory: file:/$LIB/smb.cgi?//server/share # file:/$LIB/smb.cgi?//server/share/dir... # Get file: file:/$LIB/smb.cgi?//server/share/dir.../file # # ----- ~/.w3m/smb ----- # workgroup = # username = # password = # ---------------------- $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"}; &load_auth_file($AUTH_FILE); $NMBLOOKUP = "nmblookup"; $SMBCLIENT = "smbclient"; @NMBLOOKUP_OPT = ("-T"); @SMBCLIENT_OPT = ("-N"); $USE_OPT_A = &check_opt_a(); if ($USE_OPT_A) { undef $USER; undef $PASSWD; push(@SMBCLIENT_OPT, "-A", $AUTH_FILE); } $PAGER = "cat"; $FILE = "F000"; $CGI = "file://" . &file_encode($ENV{"SCRIPT_NAME"} || $0); $QUERY = $ENV{"QUERY_STRING"}; $_ = &file_decode($QUERY); $DEBUG && print "DEBUG: QUERY_STRING=\"$_\"\n"; if (s@^//([^/]+)@@) { $server = $1; 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 "$qservice$qfile\n"; print "$qservice$qfile\n"; print "
\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 ""
			. &html_quote($_) . ""
			. &html_quote($c) . "\n";
	}
	print "
\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 "Share list: $qserver\n"; print "\n"; print "
$qserver"; for (sort @share) { ($_, $d, @c) = split(" "); if ($d eq 'Disk') { print "
+ " . &html_quote($_) . ""; } else { print "
+ " . &html_quote($_); } print "" . &html_quote($d) . "" . &html_quote("@c") . "\n"; } print "
\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 "Server list: $group\n"; print "\n"; print "
$group\n"; for (sort @server) { ($_, @c) = split(" "); print "
+ " . &html_quote($_) . "" . &html_quote("@c") . "\n"; } print "
\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 "Workgroup list\n"; print "\n"; for (sort @group) { ($_, @c) = split(" "); print "
" . &html_quote($_) . "" . &html_quote("@c") . "\n"; } print "
\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>) { /^\s*$header/ && last; } $DEBUG && print "DEBUG: $_"; 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"; if (!$USE_OPT_A && $passwd) { $ENV{"USER"} = $USER if $USER; $ENV{"PASSWD"} = $PASSWD if $PASSWD; } open(STDERR, ">/dev/null"); exec @cmd; exit 1; } sub print_form { print <
Workgroup User Password
EOF } sub load_auth_file { local($_) = @_; if ($USER =~ s/%(.*)$//) { $PASSWD = $1 unless $PASSWD; } open(F, $_) || return; while () { 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 = $_; } } close(F); } sub load_mime_type { local($_) = @_; local(%mime) = (); local($type, @suffix); open(F, $_) || return (); while() { /^#/ && 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 $_; }