1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
#!/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;
}
|