#!/usr/local/bin/perl # link.cgi # Forward the URL from path_info on to another webmin server require './servers-lib.pl'; $ENV{'PATH_INFO'} =~ /^\/(\d+)(.*)$/ || &error("Bad PATH_INFO : $ENV{'PATH_INFO'}"); $id = $1; $path = $2 ? &urlize("$2") : '/'; $path =~ s/^%2F/\//; if ($ENV{'QUERY_STRING'}) { $path .= '?'.$ENV{'QUERY_STRING'}; } elsif (@ARGV) { $path .= '?'.join('+', @ARGV); } $s = &get_server($id); &can_use_server($s) || &error($text{'link_ecannot'}); $access{'links'} || &error($text{'link_ecannot'}); $url = "$gconfig{'webprefix'}/$module_name/link.cgi/$s->{'id'}"; $| = 1; $meth = $ENV{'REQUEST_METHOD'}; if ($s->{'autouser'}) { # Login is variable .. check if we have it yet # XXX logout? # XXX upload fixed version if ($ENV{'HTTP_COOKIE'} =~ /$id=(\S+)/) { # Yes - set the login and password to use ($user, $pass) = split(/:/, &decode_base64("$1")); } else { # No - need to display a login form &ui_print_header(undef, $text{'login_title'}, ""); print "
\n"; print "
\n"; &ui_print_footer("", $text{'index_return'}); exit; } } elsif ($s->{'sameuser'}) { # Login comes from this server $user = $remote_user; defined($remote_pass) || &error($text{'login_esame'}); $pass = $remote_pass; } else { # Login is fixed $user = $s->{'user'}; $pass = $s->{'pass'}; } # Connect to the server $con = &make_http_connection($s->{'host'}, $s->{'port'}, $s->{'ssl'}, $meth, $path); &error($con) if (!ref($con)); # Send request headers &write_http_connection($con, "Host: $s->{'host'}\r\n"); &write_http_connection($con, "User-agent: Webmin\r\n"); $auth = &encode_base64("$user:$pass"); $auth =~ s/\n//g; &write_http_connection($con, "Authorization: basic $auth\r\n"); if ($ENV{'HTTP_HOST'} =~ /^(\S+):(\d+)$/) { $http_host = $1; $http_port = $2; } elsif ($ENV{'HTTP_HOST'}) { $http_host = $ENV{'HTTP_HOST'}; $http_port = 80; } else { $http_host = $ENV{'SERVER_NAME'}; $http_port = $ENV{'SERVER_PORT'}; } &write_http_connection($con, sprintf( "Webmin-servers: %s://%s:%d/%s\n", $ENV{'HTTPS'} eq "ON" ? "https" : "http", $http_host, $http_port, $tconfig{'inframe'} ? "" : "$module_name/")); $cl = $ENV{'CONTENT_LENGTH'}; &write_http_connection($con, "Content-length: $cl\r\n") if ($cl); &write_http_connection($con, "Content-type: $ENV{'CONTENT_TYPE'}\r\n") if ($ENV{'CONTENT_TYPE'}); &write_http_connection($con, "\r\n"); if ($cl) { &read_fully(STDIN, \$post, $cl); &write_http_connection($con, $post); } # read back the headers $dummy = &read_http_connection($con); while(1) { ($headline = &read_http_connection($con)) =~ s/\r|\n//g; last if (!$headline); $headline =~ /^(\S+):\s+(.*)$/ || &error("Bad header"); $header{lc($1)} = $2; $headers .= $headline."\n"; } $defport = $s->{'ssl'} ? 443 : 80; if ($header{'location'} =~ /^(http|https):\/\/$s->{'host'}:$s->{'port'}(.*)$/ || $header{'location'} =~ /^(http|https):\/\/$s->{'host'}(.*)/ && $s->{'port'} == $defport) { # fix a redirect &redirect("$url$2"); exit; } elsif ($header{'www-authenticate'}) { # Invalid login if ($s->{'autouser'}) { print "Set-Cookie: $id=; path=/\n"; &error(&text('link_eautologin', $s->{'host'}, "$gconfig{'webprefix'}/$module_name/link.cgi/$id/")); } else { &error(&text('link_elogin', $s->{'host'}, $user)); } } else { # just output the headers print $headers,"\n"; } # read back the rest of the page if ($header{'content-type'} =~ /text\/html/ && !$header{'x-no-links'}) { # Fix up HTML while($_ = &read_http_connection($con)) { s/src='(\/[^']*)'/src='$url$1'/gi; s/src="(\/[^"]*)"/src="$url$1"/gi; s/src=(\/[^ "'>]*)/src=$url$1/gi; s/href='(\/[^']*)'/href='$url$1'/gi; s/href="(\/[^"]*)"/href="$url$1"/gi; s/href=(\/[^ >"']*)/href=$url$1/gi; s/action='(\/[^']*)'/action='$url$1'/gi; s/action="(\/[^"]*)"/action="$url$1"/gi; s/action=(\/[^ "'>]*)/action=$url$1/gi; s/\.location\s*=\s*'(\/[^']*)'/.location='$url$1'/gi; s/\.location\s*=\s*"(\/[^']*)"/.location="$url$1"/gi; s/window.open\("(\/[^"]*)"/window.open\("$url$1"/gi; s/name=return\s+value="(\/[^"]*)"/name=return value="$url$1"/gi; s/param\s+name=config\s+value='(\/[^']*)'/param name=config value='$url$1'/gi; s/param\s+name=config\s+value="(\/[^']*)"/param name=config value="$url$1"/gi; s/param\s+name=config\s+value=(\/[^']*)/param name=config value=$url$1/gi; print; } } elsif ($header{'content-type'} =~ /text\/css/ && !$header{'x-no-links'}) { # Fix up CSS while($_ = &read_http_connection($con)) { s/url\("(\/[^"]*)"\)/url\("$url$1"\)/gi; print; } } else { # Just pass through while($buf = &read_http_connection($con, 1024)) { print $buf; } } &close_http_connection($con);