get packages from cvs through firewall



Hello
I have written two scripts which allow to checkout or rdiff from CVS by web.
I can't access CVS because of firewall. Hope it useful for people like me.
cvs.cgi is the cgi script. You put it on web server. The result of this
script will be translated by translate_cvs.pl.
The scripts are simple. They don't support password and other commands of cvs.
#!/usr/bin/perl

use CGI ':standard';
use Socket;

sub die_html {
    print "ERROR: @_\nERROR: $!\n";
    exit 0;
}

if (param('start') ne "start") {
    $ENV{'SCRIPT_NAME'}=~ s#^/?#/#;
    print <<EOF;
Content-type: text/html

<html><title>CVS Query</title>
<body>Valid commands are: checkout, rdiff, rtag.<p>
An additional command is "gzip &lt;level&gt;" which is like the param "-z &lt;level&gt;".<p>
<form action="$ENV{'SCRIPT_NAME'}">
<input type=hidden name="start" value="start">
<table border=0 witdh=100%>
<tr><td width=7% Valign=top>CVS Host:</td>
<td><input type=textbox name="host" size=50 value="localhost"></td></tr>
<tr><td Valign=top>Repositry dir:</td>
<td><input type=textbox name="root" size=50 value="/home/pclouds/cvsroot"></td></tr>
<tr><td Valign=top>User:</td>
<td><input type=textbox name="user" size=50 value="cvs"></td><tr>
<td Valign=top>Command:</td>
<td><textarea name="command" rows=5 cols=50 wrap=soft>co splitvt</textarea></td></tr>
<tr><td></td><td><input type=submit value="Run"></td></tr>
</table></form></body></html>
EOF
    exit 0;
}

print "Content-types: plain/text\n\n";

$root = param('root');
$host = param('host');
$user = param('user');	
$port = 2401;
$command = param('command');
$command =~ s/\r/\n/sg;
$command .= "\n";

print "Host=$host\nRoot=$root\nUser=$user\n\n";
	
$| = 1;	
$buf = "";
$output = \*STDOUT;
%valid_cmd = (co => "ok", rdiff => "ok", rtag => "ok",
	      gzip => "ok", output => "ok");

$password = "A";

$iaddr = inet_aton($host) || die_html "No host";
$cmd_authen="BEGIN AUTH REQUEST\n$root\n$user\n$password\nEND AUTH REQUEST\n";
$cmd_init = "Root $root\n";

socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp')) || die_html("Create socket failed") ;
connect(SOCK, sockaddr_in($port,$iaddr)) || die_html("Connect failed") ;
select((select(SOCK), $|=1)[0]) ;      # unbuffer the socket
$sock = \*SOCK;
print $sock $cmd_authen;
$line = read_line();
die_html "Authentication failed" if ($line ne "I LOVE YOU");
print $sock $cmd_init;
print "START\n";

while (1) {
    do {
	if ($command =~ /^([^\n]+)\n/) {
	    $cmdline = $1;
	} else {
	    print "QUIT\n";
	    exit 0;
	}
	print "CMD $cmdline\n";
	$command =~ s/^[^\n]*\n+//s;
	@param = split (/ +/,$cmdline);
	$cmd = shift @param;
    } while ($valid_cmd{$cmd} ne "ok");

    $cmd="co" if ($cmd eq "checkout");
    
    if ($cmd eq "gzip") {
	print $sock "gzip-file-contents $param[0]\n";
	next;
    }

    if ($cmd eq "output") {
	$cmdline =~ /^output (.*)/;
	open HANDLE, $1;
	$output = \*HANDLE if defined (HANDLE);
	next;
    }

    foreach $str (@param) {
	print $sock "Argument $str\n";
    }
    print $sock "$cmd\n";

    do {
	$line = read_line();
	print $output $line."\n";

	if ($line =~ /^M (.*)$/) {
	    print "MSG $1\n";
	} elsif ($line =~ /^E (.*)$/) {
	    print "ERR $1\n";
	} elsif ($line =~ /^Updated (.*)$/) {
	    $path = read_line();
	    $entry = read_line();
	    $mode = read_line();
	    print "UPDATE <$1> <$path> <$entry> <$mode>\n";
	    &get_file;
	} else {
	    print "WOW <$line>\n";
	}
    } while ($line ne "ok" and $line !~ /^error/);
}

sub read_line {
    local ($len, $buffer);

    while ($buf !~ /^[^\n]*\n/) {
	$len = sysread $sock,$buffer,1024;
	$buf = $buf . $buffer;
    }

    $buf =~ /^([^\n]*)\n/;
    $buffer = $1;
    $buf =~ s/[^\n]*\n//;
    return $buffer;
}

sub get_file {
    local ($size, $len, $realsize);
    $size = read_line();
    $size = $1 if ($size =~ /^z(.*)/);
    print "GET $size\n";
    
    if (length($buf)) {
	$realsize = $size < length($buf) ? $size : length($buf);
	$buf =~ /^(.{$realsize})/s;
	print "$1";
	$buf =~ s/^.{$realsize}//s;
	$size -= $realsize;
    }
    
    while ($size > 0) {
	$realsize = $size < 1024 ? $size : 1024;
	$len = sysread $sock,$buffer,$realsize;
	print  "$buffer";
	#print RAW $buffer;
	$size -= $len;
    }
    print "GET DONE\n";
}

Attachment: translate_cvs.pl
Description: Perl program



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