Yep, lebaudy.net seems to be alive no more. I dig up the script in the google's cache, and you can find it here (hopefully the author will not protest):
#!/usr/bin/perl
package main;
#
# Hello, this is my first perl cgi script for chumby
# As you reading this code, i am new in perl lenguage.
# I hat magic things nobody understands so i try to write useful information as i write code.
# Feel free to use this file and modify it. I hope everybody will start writing cgi perl scripts easyly.
#
#
# Author : Christian LEBAUDY
# MSN : clebaudy@hotmail.com
#
#
#
#
# You can find a lot of perl tutorials to learn the lenguage just use google : perl tutorial
# for example : http://www.cs.cmu.edu/cgi-bin/perl-man
# I provide complementary information i needed to write cgi without the CGI.pm library (chumby does not come with it)
#
# CGI perl environment variable accessible via $ENV{'variable name'} when running from the webserver
# GATEWAY_INTERFACE The revision of the Common Gateway Interface that the server uses.
# SERVER_NAME The server's hostname or IP address.
# SERVER_SOFTWARE The name and version of the server software that is answering the client request.
# SERVER_PROTOCOL The name and revision of the information protocol the request came in with.
# SERVER_PORT The port number of the host on which the server is running.
# REQUEST_METHOD The method with which the information request was issued.
# PATH_INFO Extra path information passed to a CGI program.
# PATH_TRANSLATED The translated version of the path given by the variable PATH_INFO.
# SCRIPT_NAME The virtual path (e.g., /cgi-bin/program.pl) of the script being executed.
# DOCUMENT_ROOT The directory from which Web documents are served.
# QUERY_STRING The query information passed to the program. It is appended to the URL with a "?".
# REMOTE_HOST The remote hostname of the user making the request.
# REMOTE_ADDR The remote IP address of the user making the request.
# AUTH_TYPE The authentication method used to validate a user.
# REMOTE_USER The authenticated name of the user.
# REMOTE_IDENT The user making the request. This variable will only be set if NCSA IdentityCheck flag is enabled, and the client machine supports the RFC 931 identification scheme (ident daemon).
# CONTENT_TYPE The MIME type of the query data, such as "text/html".
# CONTENT_LENGTH The length of the data (in bytes or the number of characters) passed to the CGI program through standard input.
# HTTP_FROM The email address of the user making the request. Most browsers do not support this variable.
# HTTP_ACCEPT A list of the MIME types that the client can accept.
# HTTP_USER_AGENT The browser the client is using to issue the request.
# HTTP_REFERER The URL of the document that the client points to before accessing the CGI program.
#
#
# My script constants (it is better to use constants when naming HTTP parameters or other internal stuff, this avoids errors
# when accessing parameters.
#
$HTTP_PARAMETER_ACTION="action";
$HTTP_PARAMETER_STREAM_COUNT="stream_count";
$HTTP_PARAMETER_URL="url";
$HTTP_PARAMETER_NAME="name";
$HTTP_PARAMETER_MIME_TYPE="mime_type";
$HTTP_PARAMETER_ID="id";
$HTTP_PARAMETER_MP3_ID="mp3_id";
$HTTP_PARAMETER_MP3_PATH="mp3_path";
$HTTP_PARAMETER_MP3_NAME="mp3_name";
$ACTION_SAVE="save";
$ACTION_STOP_PLAYBACK="stop_playback";
$ACTION_START_PLAYBACK="start_playback";
$HTTP_STREAM_PLAYBACK="play_stream";
$ACTION_SET_MP3="setMp3Path";
$ACTION_CHOOSE_MP3="chooseMP3";
%MIME_TYPES=("MP3", "audio/mpeg", "PLS", "audio/x-scpls", "M3U", "audio/x-mpegurl", "OGG", "application/ogg");
#
#
# useful functions
package Stream;
sub new{
my $class = shift;
my $self = {
name => shift,
url => shift,
id => shift,
mime => shift,
};
bless $self, $class;
return $self;
}
1;
package main;
sub urlDecode {
my $theURL = $_[0];
$theURL =~ tr/+/ /;
$theURL =~ s/%([a-fA-F0-9]{2,2})/chr(hex($1))/eg;
$theURL =~ s/<!--(.|\n)*-->//g;
return $theURL;
}
sub urlEncode {
my $theURL = $_[0];
$theURL =~ s/([\W])/"%" . uc(sprintf("%2.2x",ord($1)))/eg;
return $theURL;
}
sub readFile {
my $file = $_[0];
open(FILE, $file) || die("Could not open file ".$file);
@streams_file=<FILE>;
close(FILE);
return "@streams_file";
}
sub writeFile {
my $file = $_[0];
my $text = $_[1];
open(FILE, ">".$file) || die("Could not open file ".$file);
print FILE $text;
close(FILE);
}
sub getHTTPparameters {
my $request = $_[0];
%http_parameters;
foreach $param (split(/&/, $request)){
# reading each request parameter
@parameter=split(/=/, $param);
$name=$parameter[0];
$value=$parameter[1];
if( $value ){
# adding parameter name/value pair to the associative array only if value is not null
$http_parameters{urlDecode($name)} = urlDecode($value);
}
}
return %http_parameters;
}
sub getXMLValue {
my $xmlstring = $_[0];
my $name = $_[1];
$stringToFind=$name."=\"";
$value=substr($xmlstring, index($xmlstring, $stringToFind)+length($stringToFind));
$value=substr($value, 0, index($value, "\""));
return $value;
}
sub parseStreams {
my $xml = $_[0];
@streams;
foreach $stream (split(/<stream /, $xml)){
if ( $stream =~ /url=/ && $stream =~ /id=/ && $stream =~ /name=/ ){
$stream=~s/\n/ /g;
$url=getXMLValue($stream, "url");
$name=getXMLValue($stream, "name");
$id=getXMLValue($stream, "id");
$mime=getXMLValue($stream, "mimetype");
$stream=new Stream($name, $url, $id, $mime);
push(@streams, $stream);
}
}
return @streams;
}
sub generateId {
my $nb = $_[0];
$id_prefix="xxxxxxxx-yyyy-zzzz-wwww-";
$suffix=$nb."";
while( length($suffix)<12 ){
$suffix="0".$suffix;
}
return $id_prefix.$suffix;
}
sub listFiles {
my $dir = $_[0];
my $recurse = $_[1];
if( !$recurse ){
$recurse=false;
}
opendir(DIR, $dir);
my @files = readdir(DIR);
closedir(DIR);
my @list;
foreach $file (@files) {
if( !($file eq "." || $file eq "..") ){
if( recurse ){
# listing sub dir, as if( -d $file ) test does not work i don t know if it is a directory, i try with all files
my @sublist=listFiles($dir."/".$file, true);
push(@list, @sublist);
}
push(@list, "$dir/".$file);
}
}
return @list;
}
sub ascii_to_hex ($){
## Convert each ASCII character to a two-digit hex number.
(my $str = shift) =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg;
return $str;
}
sub hex_to_ascii ($){
## Convert each two-digit hex number back to an ASCII character.
(my $str = shift) =~ s/([a-fA-F0-9]{2})/chr(hex $1)/eg;
return $str;
}
sub hashCode {
my $string = $_[0];
my $hash=0;
foreach $char (split(//,$string)) {
$hash = 31*$hash+ord($char);
}
return $hash."";
}
sub stopPlayback {
system "/usr/bin/killall -9 btplayd>/dev/null 2>&1";
}
sub startPlayback {
my $url = $_[0];
# before playback testing in /tmp/stream_playback file it is not started to play with another thread
# for stupid reasons web browser sometimes sends 2 HTTP requests simultaneously and thi smakes problems
# playback starts and then stops, timestamp testing avoids that
my $tempFile="/tmp/stream_playback";
my $lastTimestamp=0;
if( -e $tempFile && -R $tempFile ){
$lastTimestamp=readFile($tempFile);
}
my $timestamp=time; # it is only one second resolution;
if( $timestamp > ($lastTimestamp+10) ){
# we do not allow multiple http requests between 10 s
writeFile($tempFile, $timestamp);
sleep(1);
if( -e $tempFile && -R $tempFile ){
$fileTimestamp=readFile($tempFile);
}
if( $fileTimestamp eq $timestamp || $timestamp > ($lastTimestamp+10) ){
stopPlayback();
system "/usr/bin/chumby_set_volume 75>/dev/null 2>&1";
system "/usr/bin/btplay --start-daemon --output=alsa:plug:dmixer \"".$url."\" 1 >/dev/null 2>&1 ;";
}
}
}
#
# variable web will be tested to know wether we are running in the webserver or not
$web=$ENV{'REQUEST_METHOD'};
$request=$ENV{'QUERY_STRING'};
$uri=$ENV{'SCRIPT_NAME'};
# url_streams file
$url_streams_file="/psp/url_streams";
# getting HTTP POST data
if( $web eq "POST" ){
# POST data is given as the standard input of the process
@input=<STDIN>;
$request="@input";
}
# only for tests purposes
if( !$web ){
$request="name_1=Ibiza+Global+Radio&url_1=http%3A%2F%2Fs6.viastreaming.net%3A7010%2Flisten.pls&id_1=xxxxxxxx-yyyy-zzzz-wwww-1&name_2=ODS+Radio&url_2=http%3A%2F%2Fstatslive.infomaniak.ch%2F%7Eradios%2Fradios%2Ffiles%2Fods%2Fods-high.pls&id_2=xxxxxxxx-yyyy-zzzz-wwww-2&name_3=minichalet+radio&url_3=http%3A%2F%2F192.168.0.5%3A8000%2Flisten.pls&id_3=xxxxxxxx-yyyy-zzzz-wwww-3&name_4=&url_4=&id_4=xxxxxxxx-yyyy-zzzz-wwww-4";
$url_streams_file="/psp/url_streams";
}
# associative array that will contain the HTTP request parameters name/value pairs
%http_parameters=getHTTPparameters($request);
$action=$http_parameters{$HTTP_PARAMETER_ACTION};
if( $action eq $ACTION_SAVE ){
$nb=$http_parameters{$HTTP_PARAMETER_STREAM_COUNT};
# generating new url_streams file xml content
$xml_url_streams = "<streams>\n";
for ($i=1; $i<=$nb; ++$i){
$name=$http_parameters{$HTTP_PARAMETER_NAME."_".$i};
$url=$http_parameters{$HTTP_PARAMETER_URL."_".$i};
$id=$http_parameters{$HTTP_PARAMETER_ID."_".$i};
$mime=$http_parameters{$HTTP_PARAMETER_MIME_TYPE."_".$i};
if( $url && $name ){
$xml_url_streams.=" <stream url=\"".$url."\"\n";
$xml_url_streams.=" id=\"".$id."\"\n";
$xml_url_streams.=" mimetype=\"".$mime."\"\n";
$xml_url_streams.=" name=\"".$name."\" />\n";
}
}
$xml_url_streams.="</streams>\n";
writeFile($url_streams_file, $xml_url_streams);
}
# reading url_streams file
$xml_content=readFile($url_streams_file);
# parsing streams XML
@streams=parseStreams($xml_content);
if( $web ){
# Code running inside web server when script is invoked by cgi framework
if( $action eq $ACTION_STOP_PLAYBACK ){
stopPlayback();
}
if( $action eq $ACTION_START_PLAYBACK ){
stopPlayback();
$streamToPlay=$http_parameters{$HTTP_STREAM_PLAYBACK};
startPlayback($streamToPlay);
}
if( $action eq $ACTION_CHOOSE_MP3 ){
$mp3id=$http_parameters{$HTTP_PARAMETER_MP3_ID};
@listing=listFiles("/mnt", true);
@mp3s;
foreach $file (@listing) {
if( $file =~ /\.mp3$/ ){
push(@mp3s, $file);
}
}
@mp3s=sort(@mp3s);
$mp3count=scalar(@mp3s);
print "HTTP/1.1 200 ok\n",
"Content-type: text/html\n",
"#\n",
"\n",
"<HTML>\n",
"<HEAD><TITLE>My streams</TITLE>\n",
"<script type=\"text/javascript\">\n",
"function selectFile(file, name){\n",
" document.inputForm.", $HTTP_PARAMETER_MP3_PATH, ".value=file;\n",
" document.inputForm.", $HTTP_PARAMETER_MP3_NAME, ".value=name;\n",
" document.inputForm.submit();\n",
"}\n",
"</script>\n",
"</HEAD>\n",
"<BODY bgcolor=\"#cccccc\" text=\"#000000\">\n",
"<CENTER><img src=\"/images/chumby_logo.png\"></CENTER><BR>",
"<CENTER><H1>Choose an MP3 on the chumby filesystem to use as stream.</H1></CENTER>\n",
"<BR><P>Back to <a href=\"", $uri, "\">My streams configuration page</a></P>\n",
"<HR>\n";
if( $mp3count > 0 ){
print "<TABLE BORDER=\"0\">\n";
foreach $mp3 (@mp3s) {
# computing file name alone without .mp3 extension and full path
$name=substr($mp3, 0, length($mp3)-4);
while( ($ix=index($name, "/"))>=0 ){
$name=substr($name, $ix+1);
}
print "<TR>",
"<TD> <INPUT TYPE=\"BUTTON\" NAME=\"select\" VALUE=\"", $mp3, "\"",
" onclick=\"javascript:selectFile('", $mp3, "', '", $name, "')\"></INPUT>\n</TD></TR>\n";
}
print "</TABLE>";
}else{
print "<H2>Sorry no mp3 found in all /mnt mount drives.</H2>\n",
"<BR>\n";
}
print "<BR>\n",
"<FORM NAME=\"inputForm\" METHOD=\"post\" ACTION=\"", $uri, "\">\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_PARAMETER_ACTION, "\" VALUE=\"", $ACTION_SET_MP3, "\">\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_PARAMETER_MP3_PATH, "\" VALUE=\"\">\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_PARAMETER_MP3_NAME, "\" VALUE=\"\">\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_PARAMETER_MP3_ID, "\" VALUE=\"", $mp3id, "\">\n",
"</FORM>\n",
"</BODY>\n",
"</HTML>\n";
}else{
if( $action eq $ACTION_SET_MP3 ){
$mp3Path=$http_parameters{$HTTP_PARAMETER_MP3_PATH};
$mp3Name=$http_parameters{$HTTP_PARAMETER_MP3_NAME};
$urlId=$http_parameters{$HTTP_PARAMETER_MP3_ID};
}
print "HTTP/1.1 200 ok\n",
"Content-type: text/html\n",
"#\n",
"\n",
"<HTML>\n",
"<HEAD><TITLE>My streams</TITLE>\n",
"<script type=\"text/javascript\">\n",
"function clearField(f_name,f_url){\n",
" f_name.value = '';\n",
" f_url.value = '';\n",
" submitForm();\n",
"}\n",
"function submitForm(){\n",
" document.inputForm.save_button.disabled = true;\n",
" i = 0;\n",
" for(i=0;i<document.inputForm.elements.length;i++){\n",
" if( document.inputForm.elements[i].type == 'button' ){\n",
" document.inputForm.elements[i].disabled = true;\n",
" }\n",
" }\n",
" document.inputForm.submit();\n",
"}\n",
"function stopPlay(){\n",
" document.inputForm.", $HTTP_PARAMETER_ACTION, ".value='", $ACTION_STOP_PLAYBACK, "';\n",
" document.inputForm.submit();\n",
"}\n",
"function startPlay(stream){\n",
" document.inputForm.", $HTTP_PARAMETER_ACTION, ".value='", $ACTION_START_PLAYBACK, "';\n",
" document.inputForm.", $HTTP_STREAM_PLAYBACK, ".value=stream;\n",
" document.inputForm.submit();\n",
"}\n",
"function selectMp3(id){\n",
" document.inputForm.", $HTTP_PARAMETER_ACTION, ".value='", $ACTION_CHOOSE_MP3, "';\n",
" document.inputForm.", $HTTP_PARAMETER_MP3_ID, ".value=id;\n",
" document.inputForm.submit();\n",
"}\n",
"</script>\n",
"</HEAD>\n",
"<BODY bgcolor=\"#cccccc\" text=\"#000000\">\n",
"<CENTER><img src=\"/images/chumby_logo.png\"></CENTER>",
"<CENTER><H1>My streams configuration page</H1></CENTER>\n",
"<center><a href=\"/\">back</a></center><br>",
"<BR>\n",
"<FORM NAME=\"inputForm\" METHOD=\"post\" ACTION=\"", $uri, "\">\n",
"<TABLE BORDER=\"0\">\n",
"<TR><TD>Radio Name :</TD><TD>URL ( supports PLS, M3U, MP3, Ogg) :</TD><TD> </TD><TD> </TD><TD> </TD>",
"<TD><INPUT TYPE=\"BUTTON\" VALUE=\"Stop playback\" onclick=\"javascript:stopPlay()\"></INPUT></TD>\n";
$i=1;
foreach $stream (@streams){
$url=$stream->{url};
$name=$stream->{name};
$mime=$stream->{mime};
if( $mp3Path && $i==$urlId ){
$url=$mp3Path;
$name=$mp3Name;
$mime=$MIME_TYPES{"MP3"};
}
print "<TR><TD><INPUT TYPE=\"text\" NAME=\"", $HTTP_PARAMETER_NAME."_".$i,"\" SIZE=\"30\" VALUE=\"", $name, "\"></TD>\n",
"<TD><INPUT TYPE=\"text\" NAME=\"", $HTTP_PARAMETER_URL."_".$i, "\" SIZE=\"80\" VALUE=\"", $url, "\"></TD>\n",
"<TD><select name=\"", $HTTP_PARAMETER_MIME_TYPE."_".$i, "\">\n";
foreach $mimeName (keys(%MIME_TYPES)) {
$selected="";
if( $MIME_TYPES{$mimeName} eq $mime ){
$selected="selected";
}
print "<option value=\"", $MIME_TYPES{$mimeName}, "\" ", $selected, ">", $mimeName, "</option>";
}
print "</select></TD>\n",
"<TD><INPUT TYPE=\"BUTTON\" VALUE=\"choose mp3\" onclick=\"javascript:selectMp3(", $i, ")\"></INPUT></TD>\n",
"<TD><INPUT TYPE=\"BUTTON\" VALUE=\"remove\" onclick=\"javascript:clearField(this.form.name_", $i, ",this.form.url_", $i, ")\"></INPUT></TD>\n";
if( $mime eq $MIME_TYPES{"MP3"} ){
print "<TD><INPUT TYPE=\"BUTTON\" VALUE=\"Start playback\" onclick=\"javascript:startPlay('", $url, "')\"></INPUT></TD>\n";
}else{
print "<TD> </TD>\n";
}
"</TR>\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_PARAMETER_ID."_".$i, "\" VALUE=\"", generateId($i), "\">\n";
++$i;
}
$url="";
$name="";
if( $mp3Path && $i==$urlId ){
$url=$mp3Path;
$name=$mp3Name;
}
print "<TR><TD><INPUT TYPE=\"text\" NAME=\"", $HTTP_PARAMETER_NAME."_".$i,"\" SIZE=\"30\" VALUE=\"", $name, "\"></TD>\n",
"<TD><INPUT TYPE=\"text\" NAME=\"", $HTTP_PARAMETER_URL."_".$i, "\" SIZE=\"80\" VALUE=\"", $url, "\"></TD>\n",
"<TD><select name=\"", $HTTP_PARAMETER_MIME_TYPE."_".$i, "\">\n";
foreach $mime (keys(%MIME_TYPES)) {
print "<option value=\"", $MIME_TYPES{$mime}, "\">", $mime, "</option>";
}
print "</select></TD>\n",
"<TD><INPUT TYPE=\"BUTTON\" VALUE=\"choose mp3\" onclick=\"javascript:selectMp3(", $i, ")\"></INPUT></TD>\n",
"<TD> </TD></TR>\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_PARAMETER_ID."_".$i, "\" VALUE=\"", generateId($i), "\">\n",
"</TABLE>\n";
if( $mp3Path ){
print "<font color=\"red\"><p>Careful, this hasn't been saved yet. Please click on the button below to accept changes:<p></font>\n";
}
print "<INPUT TYPE=\"BUTTON\" NAME=\"save_button\" VALUE=\"Save\" onclick=\"javascript:submitForm()\"></INPUT>\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_PARAMETER_STREAM_COUNT, "\" VALUE=\"", $i, "\">\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_PARAMETER_ACTION, "\" VALUE=\"", $ACTION_SAVE, "\">\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_STREAM_PLAYBACK, "\" VALUE=\"\">\n",
"<INPUT TYPE=\"hidden\" NAME=\"", $HTTP_PARAMETER_MP3_ID, "\" VALUE=\"\">\n",
"</FORM>\n",
"<HR>\n",
"<BR>\n",
#"<PRE>\n",
#"REQUEST_METHOD=", $web, "\n",
#"QUERY_STRING=", $request, "\n",
#"action : ", $http_parameters{$HTTP_PARAMETER_ACTION}, "\n",
#"</PRE>\n",
"</BODY>\n",
"</HTML>\n";
}
}else{
# Test code running outside web server when script is invoked directly from command line
print "Running outside webserver\n";
print urlDecode("%31+%32%0A%33+%34"), "\n";
print "request=$request\n";
print "name_1=", $http_parameters{"name_1"}, "\n";
$n=2;
print "name_2=", $http_parameters{"name_".$n}, "\n";
print "Number of HTTP parameters : ", scalar(keys %http_parameters),"\n";
print $xml_content, "\n";
$s=new Stream("Radio", "listen.pls", "0");
print $s->{name}, "\n";
print scalar(@streams)," streams found.", "\n";
foreach $stream (@streams){
print "Stream ", $stream->{name}, " with url ", $stream->{url}, "\n";
}
print "id=", generateId(4), "\n";
writeFile("testfile.txt", "Some text in the file.\nAnother line\n");
$text= "some text\n".
"continuing here\n";
$text.="\nmore text.";
print $text."\n\n";
print $text."\n\n";
print "Listing files in /mnt\n";
@listing=listFiles("/mnt", true);
foreach $file (@listing) {
if( $file =~ /.mp3$/ ){
print "mp3 file : ", $file, "\n";
}
}
print "\n\n";
print keys(%MIME_TYPES);
print "\n\n";
$mp3path="/some/path/mp3";
if( $mp3path =~ /\.mp3$/ ){
print "file is an mp3\n";
}
$mp3path="/some/path/titi.mp3";
if( $mp3path =~ /\.mp3$/ ){
print "titi is an mp3\n";
}
$hash=hashCode("http://statslive.infomaniak.ch/~radios/radios/files/ods/ods-high.pls");
print "hash=", ascii_to_hex($hash), "\n";
#stopPlayback();
#startPlayback("/mnt/usb/mp3/Celia Cruz - La vida es un carnaval.mp3");
$time=time;
print "time is : ", $time, "\n";
}