/contrib/famzah

Enthusiasm never stops


Leave a comment

Perl API Kit for ResellerClub (DirectI)

ResellerClub offer a SOAP/WSDL API interface, in addition to their Online Control Panel, which lets you automate some of your tasks or integrate it directly with your website.

They claim to support a Perl API Kit, but it doesn’t work out-of-the box for me. Whenever I make an API call, I get the following:

soapenv:Server.userException java.lang.Exception: Body not found.

There is a similar bug report at Web Hosting Talk too.

After a few hours of struggling with SOAP::Lite, reading sources, and some trial and error, I finally was able to make the API work in Perl! 😀

If you want to try my version of their Perl API Kit, you have to execute the following:

wget --no-verbose http://www.famzah.net/download/resellerclub/resellerclub-api.tgz
tar -zxf resellerclub-api.tgz
cd resellerclub-api

vi example.pl # edit your username/password
./example.pl

In order to build my version of the Perl API Kit yourself, click the “show source” link below and execute the commands.

mkdir resellerclub-api
cd resellerclub-api
wget --no-verbose http://www.famzah.net/download/resellerclub/setup.sh
wget --no-verbose http://www.famzah.net/download/resellerclub/example.pl
chmod +x setup.sh example.pl
./setup.sh

vi example.pl # edit your username/password
./example.pl

The scripts use some Debian/Ubuntu specific “apt-get” commands to install the required Perl and system packages, but this can easily be ported to other *nix systems too.


2 Comments

Auto-flush both STDOUT and STDERR in Perl

Q: Why Perl warn() or other STDERR output is not shown/logged/saved/flushed into my log file?
A: You may have encountered the well-known feature of stream buffering which is enabled by default.

An excerpt from the perlvar documentation says that “…STDOUT will typically be line buffered if output is to the terminal and block buffered otherwise”. Thus it is always buffered, also for STDERR.

Usually people remember to set STDOUT as auto-flush, but you should enable this for STDERR as well, or else your messages to STDERR may not appear in your log file immediately, if you are redirecting STDERR to a file.

The following piece of code sets an auto-flush for both STDOUT and STDERR:

select(STDERR);
$| = 1;
select(STDOUT); # default
$| = 1;

The select() function and the $| variable are built-in for Perl and require no additional libraries to be included.

Alternatively, you can also use IO::Handle to achieve the same result:

use IO::Handle;
STDERR->autoflush(1);
STDOUT->autoflush(1);

I never realized why stream buffering for both STDOUT and STDERR is enabled by default for most scripting languages… But that’s just me.


References:


Leave a comment

Properly construct the HTTP Content-Length request header

Occasionally I need to make an HTTP request via telnet for debug purposes – either I want to easily see exactly what the server returned as response, or I want to tamper with the HTTP request for some reason.

There are many articles around the net which explain how to make an HTTP request via telnet. However, most of them don’t explain how to construct the “Content-Length” HTTP header, or it’s just me who can’t find the answer quickly.

The straight answer to what number do we write for content length is: the length of the body.

However, if we take a look at the following Perl example:

#!/usr/bin/perl
use strict;
use warnings;

my $url = '/post.php';
my $host = 'example.com';

my $http_post_body = <<EOF;
POST_REQUEST_LINE1
POST_REQUEST_LINE2
POST_REQUEST_LINE3
EOF

my $content_length = length($http_post_body);

# Construct the request
print <<EOF;
POST $url HTTP/1.1
Host: $host
Content-Length: $content_length

$http_post_body
EOF

The above calculated length of $content_length won’t be what the HTTP server expects, at least this is what my Apache installation shown. If you paste via telnet what the Perl script output, the HTTP server will not accept this POST request. Because the “Content-Length” is wrong.

Actually, telnet ends lines with “\r\n”, not just with “\n”. This is what Apache seems to expect for sure too, but I haven’t researched that thoroughly. Here comes the tricky part. You need to end your lines in Perl with “\r\n”, not just with “\n” as most text editors do. Therefore, before calculating the value of “Content-Length”, we need to convert the body of the HTTP request by using the following code:

...
# convert "\n" to "\r\n" endings
$http_post_body =~ s/([^\r])\n/$1\r\n/g;

my $content_length = length($http_post_body);
...

I would have published a more useful Perl example, but the reason I needed to calculate “Content-Length” for a POST HTTP request this time was because I wrote a small script as a proof-of-concept for the PHP “multipart/form-data” denial of service bug. And I’m not in a mood to make script-kiddies’ life easier 🙂 Even though our hosting servers were not vulnerable to this attack as the resource limits for the hosting accounts manage to mitigate it enough.