#!/usr/bin/perl # # This program gets the output of a specified URL. The user # specifies the host and URL as well as any parameters that might # be used by the URL. The output of URL is returned either # to standard output or to a specified file. Five special keyword # parameters may be specified: url, host, method, port and file. # All other parameters are passed to the URL. # # Webquery does no reformatting or error checking. Typically # the returned data will be an HTML formatted document. If an # error is encountered, the returned data may be an HTML formatted # error message. # # Usage: # webquery url=URL host=HOST method=METHOD port=PORT file=FILE # [key=VALUE key=VALUE] # # The default URL is the null string. The default host is the local # host. The method and port keywords may be used # to override the defaults of POST and 80 respectively. # The file keyword specifies an output file to which the response is # to be sent. If not specified, output is sent to standard output. # # # Additional keywords are appended to the URL request as # keyword values for a forms request. Webquery will appropriately # escape special characters. # $port = 80; $method = "POST"; $version = "WEBQVER=2.0"; use Socket; if (!eval {require 'Socket.pm';} ) { $socket = "false"; } else { #use Socket; $socket = "true"; } # Loop over the locally handled arguments. foreach (@ARGV) { if (/=/) { ($key, $value) = split(/=/); if ($key eq "url") { $url = $value;} elsif ($key eq "host") {$host = $value;} elsif ($key eq "method") {$method = $value;} elsif ($key eq "port") {$port = int($value);} elsif ($key eq "file") {$outfile = $value;} } } if (!$url) { $url = ""; } if (!$host) { chop ($host = `hostname`); } # Set up the socket connection. # Socket code below adapted from "Programming Perl", by Wall and Schwartz. # $AF_INET = 2; $SOCK_STREAM = 1; $sockaddr = 'S n a4 x8'; chop ($hostname = `hostname`); ($name, $aliases, $proto) = getprotobyname('tcp'); if ($socket eq "false") { # Socket.pm is not defined (or could not be found) # fall back to some defaults that are known to work # with DEC Alpha's running Digital Unix $AF_INET = 2; $SOCK_STREAM = 1; ($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname); ($name, $aliases, $type, $len, $thataddr) = gethostbyname($host); $this = pack($sockaddr, $AF_INET, 0, $thisaddr); $that = pack($sockaddr, $AF_INET, $port, $thataddr); # Make the socket file handle if (socket(S, $AF_INET, $SOCK_STREAM, $proto)) { } else { die("Webquery: Unable to create socket"); } } else { # Socket.pm can be found, so use it to make the connection $thisaddr = Socket::inet_aton($hostname); $thataddr = Socket::inet_aton($host); $this = Socket::pack_sockaddr_in(0,$thisaddr); $that = Socket::pack_sockaddr_in($port,$thataddr); if (socket(S, AF_INET, SOCK_STREAM, $proto)) { } else { die("Webquery: Unable to create socket"); } } if (bind(S, $this)) { } else { die ("Webquery: Unable to bind socket, $!"); } if (connect(S, $that)) { } else { die("Webquery: Unable to connect to $host, $!"); } # Make the socket the default output select (S); # Force immediate flushing of output $| = 1; # Go back to standard output. select (STDOUT); # Format the query string. We'll loop over all the # arguments again and this time we'll ignore the # special ones. args_loop: foreach (@ARGV) { if (/=/) { ($key, $value) = split("=", $_, 2); if ($key eq "host" || $key eq "url" || $key eq "port" || $key eq "method"|| $key eq "file") { next args_loop; } # Put in field delimiter. if ($query) {$query .= "&";} # Escape special characters. Note that # we do it for key and value separately so as not to # escape the '='. $query .= &webcode($key); $query .= "="; $query .= &webcode($value); } else { # Allow generic strings too. if ($query) {$query .= "&";} $query .= &webcode($value); } } if ($query) {$query .= "\015\012\015\012";} $method =~ tr/a-z/A-Z/; # Send the query to the server. if ($query){ if ($method eq 'POST') { print S "$method $url HTTP/1.0\012", "User_Agent: Webquery V1.0\012", "Content-type: application/x-www-form-urlencoded\012", "Content-length: ",length($query)-3,"\012\012"; print S $query; } else { print S "$method $url"."?".$query."HTTP/1.0\012", "User_Agent: Webquery V1.0\012", "Content-type: application/x-www-form-urlencoded\012"; } } else { # Usually we can only use POST if there are parameters, so convert # to GET if not. if ($method eq "POST") {$method = "GET";} print S "$method $url HTTP/1.0\012", "User_Agent: Webquery V1.0\012\012"; } # If the user specified an output file, open it and make it # the standard output. if ($outfile) { open(OUTFILE, '>'.$outfile); select(OUTFILE); } # Now read the results. while ( ($len = read(S, $buffer, 1024)) > 0) { print $buffer; } sub webcode { local ($string) = @_; # First convert special characters to to %xx notation. $string =~ s/[^ a-zA-Z0-9]/sprintf("%%%02x", ord($&))/eg ; # Now convert the spaces to +'s. # We do this last since otherwise +'s would be translated by above. $string =~ tr/ /+/; # Perl doesn't require (or even like) putting in the return value, # but I find it clearer. return $string; }