#!/usr/bin/env perl
# LWP::Simple
# HTML::Parser
# HTML::Tagset
# URI
# XML::RAI
# Date::Format
# XML::RSS::Parser
# XML::Elemental
# XML::NamespaceSupport
# Class::ErrorHandler
# Class::XPath
# Some global variable initialisation
# Do Not alter these Global definitions
my $DEBUG = "NO";
my $FixGerman = "NO";
#
# =============================================================
# Variables/items taht are user changeable or customisable
# =============================================================
#
# Add the URL of the RSS feed and a title to the array bellow
my @feeds = (
'http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/uk/rss.xml', 'BBC News UK',
'http://newsrss.bbc.co.uk/weather/forecast/28/Next3DaysRSS.xml', 'Ipswich Weather Forecast',
);
# Static sites that are not RSS feeds - just sites that have static content
my @sites = (
'http://10.134.2.152/it.xml', 'IT Help Desk',
);
# Change any of these menu strings etc as required
my $menutitle='News and Information';
my $menuprompt='Choose an Item';
my $defaultrefresh=600;
# If you want strange characters in German RSS feeds to be translated to
# hopefully correct German leave this uncomented. might break other
# character sets.
# my $FixGerman = "YES";
# Comment out if you do not want a menu option that displays the HTTP
# environment variables sent by the phone when making a request
# my $DEBUG="YES";
####################################################################
## There should be nothing to change after here
## Unless you wanna rewrite the internals
####################################################################
use strict;
use LWP::Simple qw($ua get);
use XML::RAI;
use CGI;
use URI::Escape;
my %property;
# construct url to script
$ENV{SERVER_NAME} =~ s!/+$!!;
$ENV{SCRIPT_NAME} =~ s!^/+!!;
my $pathto = "http://$ENV{SERVER_NAME}/$ENV{SCRIPT_NAME}";
# Get environment variables returned by phone web browser
getenv();
# Get phone model
my $model = $property{'HTTP_X_CISCOIPPHONEMODELNAME'};
# Determine if phone supports XML 3.1 (only newer 7970s do this
# From what we can see, 7960s with SIP iamges do XML 3.0
# XML 3.0 dose not support SoftKeyItem directive
my $age = "NEW";
if ($model =~ /79[4,6]0/) {
$age = "OLD";
}
my $query = new CGI;
my $item=$query->param('item');
my $url=$query->param('opts');
if ($url && $item)
{
printitem($url, $item, $query->param('maxitem'));
}
elsif ($url)
{
if ($url eq "DEBUG") { printenv() ; }
else { printtitles($url); }
}
else
{
printmenu();
}
sub getenv {
my $var;
my $val;
foreach $var (sort(keys(%ENV))) {
$val = $ENV{$var};
$val =~ s|\n|\\n|g;
$val =~ s|"|\\"|g;
$property{$var} = $val;
}
}
sub printenv {
my $k;
print "Content-Type: text/xml\n\n";
print "\n";
print "HTTP Header Environment";
foreach my $k (sort keys %property)
{
#print uri_escape($k).":".uri_escape($property{$k})."\n";
my $value = $property{$k};
$value =~ s/\<|\>/ /g;
print "$k:$value \n";
}
print "";
if ($age eq "NEW") {
my $pth = substr($pathto,0,255);
print "";
print " Back";
print " $pth";
print " 3";
print "";
}
print "";
}
sub printmenu {
my $pth= "$pathto?opts=";
print "Content-Type: text/xml\n\n";
#foreach my $k (sort keys %ENV)
#{
# print "$k: $ENV{$k}\n";
#}
print "\n";
print "".substr($menutitle,0,31)."".substr($menuprompt,0,31)."\n";
for (my $i = 0; $i <= ($#feeds) && $i<=64*2;)
{
my $fe = $feeds[$i++];
my $nm = $feeds[$i++];
print "\n";
}
for (my $i = 0; $i <= ($#sites) && $i<=64*2;)
{
my $fe = $sites[$i++];
my $nm = $sites[$i++];
print "\n";
}
# If DEBUG set to YES print an option to display HTTP Header
# Environment variables
if ($DEBUG eq "YES") {
print "\n";
}
print "\n";
exit 0;
}
sub printitem
{
my ($url, $item, $maxitem) = @_;
my $maxlength=4000;
my $rai=XML::RAI->parse(getfeed($url));
printmenu() unless $rai;
my $title=''; $title=substr(cmxml_escape($rai->channel->title),0,31) if $rai->channel->title;
my $it=${$rai->items}[$item-1]; # get item
my $date=''; $date=substr(cmxml_escape($it->issued),0,31) if $it->issued;
my $txt='';
$txt .= cmxml_escape("$item: ".$it->title) if $it->title;
$txt .= "\n--------------------------------\n";
$txt .= cmxml_escape($it->content) if $it->content;
my $txt1 = $it->content;
$txt=substr($txt,0,3999);
print "Content-Type: text/xml\n\n";
print "\n";
print "";
print "$title" if $title;
print "$date" if $date;
print "$txt";
#print "$txt1";
if ($age eq "NEW") {
if($item>1)
{
my $i=$item-1;
my $pth = substr("$pathto?opts=".uri_escape($url)."\&maxitem=$maxitem\&item=$i",0,255);
print "";
print " <<";
print " $pth";
print " 1";
print "";
}
if($item<$maxitem)
{
my $i=$item+1;
my $pth = substr("$pathto?opts=".uri_escape($url)."\&maxitem=$maxitem\&item=$i",0,255);
print "";
print " >>";
print " $pth";
print " 2";
print "";
}
}
if ($age eq "NEW") {
my $pth = substr("$pathto?opts=".uri_escape($url),0,255);
print "";
print " Back";
print " $pth";
print " 3";
print "";
}
print "\n";
}
sub printtitles {
my ($url) = @_;
my $rai=XML::RAI->parse(getfeed($url));
printmenu() unless $rai;
my $title=''; $title=substr(cmxml_escape($rai->channel->title),0,31) if $rai->channel->title;
my $date=''; $date=substr(cmxml_escape($rai->channel->issued),0,31) if $rai->channel->issued;
my $refresh=$defaultrefresh;
if($rai->channel->src->query('ttl'))
{
$refresh=$rai->channel->src->query('ttl')*60;
}
print "Content-Type: text/xml\nRefresh: $refresh\n\n";
print "\n";
print "";
print "$title" if $title;
print "$date" if $date;
my $maxitem=0;
foreach my $item (@{$rai->items}) { $maxitem++; } # todo: better array size detection
my $pth = "$pathto?opts=".uri_escape($url)."\&maxitem=$maxitem\&item=";
my $z=0;
foreach my $item (@{$rai->items})
{
last if ++$z >99;
print "\n";
}
if ($age eq "NEW") {
print "";
print " Select";
print " SoftKey:Select";
print " 1";
print "";
print "";
print " Reload";
print " ".substr($pth,0,255)."";
print " 2";
print "";
print "";
print " Back";
print " ".substr($pathto,0,255)."";
print " 3";
print "";
}
print "\n";
}
sub getfeed
{
my ($url) = @_;
my $feed;
# construct cache filename
my $fn=$url;
$fn =~ s/[^\w\d]/_/g;
$fn = "/tmp/$fn";
# check if cached rss is valid
if(-f $fn)
{
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($fn);
if($mtime > time()-($defaultrefresh-30) && $size>100)
{
open(A, $fn);
$feed.=$_ while ;
close(A);
return $feed;
}
}
# get RSS data
$ua->timeout(15);
$feed = get($url);
printmenu() if length($feed)==0;
# save into cache
open(A, ">$fn");
print A $feed;
close(A);
return $feed;
}
sub cmxml_escape
{
($_) = @_;
return unless $_;
$_=HTMLentity2latin1($_);
s/\s+/ /g; # strip ws
s/<.+?>//g; # strip html tags
# escape special chars
# s/\</g;
# s/>/\>/g;
# s/ß/\ß/g;
# s/ü/\ü/g;
#
#
# Translating German characters fudged by web browser to
# hopefully real German - list is far from complete
#
if ($FixGerman eq "YES") {
s/Ã/ü/g;
s/ü¼/ü/g;
s/ü¶/ö/g;
s/ü¤/ä/g;
s/üŸ/ß/g;
s/üœ/Ü/g;
s/Â//g;
s/ü„u/Ä/g;
s/©/é/g;
}
if ($age eq "NEW") {
# Older phone's SIP iamge web browser appear to have an issue
# with &apos and possibly " so we wont change this
s/'/\'/g; # '
s/"/\"/g; # "
}
s/\&(?!lt|gt|apos|quot|amp)/\&/g;
return $_;
}
sub HTMLentity2latin1
{
($_) = @_;
return unless $_;
s/\Æ/AE/g; s/\Æ/AE/g;
s/\Á/Á/g; s/\Á/Á/g;
s/\Â/Â/g; s/\Â/Â/g;
s/\À/À/g; s/\À/À/g;
s/\Α/A/g; s/\Α/A/g;
s/\Å/Å/g; s/\Å/Å/g;
s/\Ã/Ã/g; s/\Ã/Ã/g;
s/\Ä/Ä/g; s/\Ä/Ä/g;
s/\Β/B/g; s/\Β/B/g;
s/\Ç/Ç/g; s/\Ç/Ç/g;
s/\Χ/X/g; s/\Χ/X/g;
s/\‡/++/g; s/\‡/++/g;
s/\Δ/D/g; s/\Δ/D/g;
s/\Ð/Ð/g; s/\Ð/Ð/g;
s/\É/É/g; s/\É/É/g;
s/\Ê/Ê/g; s/\Ê/Ê/g;
s/\È/È/g; s/\È/È/g;
s/\Ε/E/g; s/\Ε/E/g;
s/\Η/H/g; s/\Η/H/g;
s/\Ë/Ë/g; s/\Ë/Ë/g;
s/\Γ/G/g; s/\Γ/G/g;
s/\Í/Í/g; s/\Í/Í/g;
s/\Î/Î/g; s/\Î/Î/g;
s/\Ì/Ì/g; s/\Ì/Ì/g;
s/\Ι/I/g; s/\Ι/I/g;
s/\Ï/Ï/g; s/\Ï/Ï/g;
s/\Κ/K/g; s/\Κ/K/g;
s/\Λ/L/g; s/\Λ/L/g;
s/\Μ/M/g; s/\Μ/M/g;
s/\Ñ/Ñ/g; s/\Ñ/Ñ/g;
s/\Ν/N/g; s/\Ν/N/g;
s/\Œ/½/g; s/\Œ/½/g;
s/\Ó/Ó/g; s/\Ó/Ó/g;
s/\Ô/Ô/g; s/\Ô/Ô/g;
s/\Ò/Ò/g; s/\Ò/Ò/g;
s/\Ω/O/g; s/\Ω/O/g;
s/\Ο/o/g; s/\Ο/o/g;
s/\Ø/Ø/g; s/\Ø/Ø/g;
s/\Õ/Õ/g; s/\Õ/Õ/g;
s/\Ö/Ö/g; s/\Ö/Ö/g;
s/\Φ/P/g; s/\Φ/P/g;
s/\Π/pi/g; s/\Π/pi/g;
s/\″/"/g;s/\″/"/g;
s/\Ψ/psi/g; s/\Ψ/psi/g;
s/\Ρ/P/g; s/\Ρ/P/g;
s/\Š/¦/g; s/\Š/¦/g;
s/\Σ/E/g; s/\Σ/E/g;
s/\Þ/Þ/g; s/\Þ/Þ/g;
s/\Τ/T/g; s/\Τ/T/g;
s/\Θ/(x)/g; s/\Θ/(x)/g;
s/\Ú/Ú/g; s/\Ú/Ú/g;
s/\Û/Û/g; s/\Û/Û/g;
s/\Ù/Ù/g; s/\Ù/Ù/g;
s/\Υ/Y/g; s/\Υ/Y/g;
s/\Ü/Ü/g; s/\Ü/Ü/g;
s/\Ξ/[x]/g; s/\Ξ/[x]/g;
s/\Ý/Ý/g; s/\Ý/Ý/g;
s/\Ÿ/¾/g; s/\Ÿ/¾/g;
s/\Ζ/Z/g; s/\Ζ/Z/g;
s/\á/á/g; s/\á/á/g;
s/\â/â/g; s/\â/â/g;
s/\´/'/g; s/\´/'/g;
s/\æ/æ/g; s/\æ/æ/g;
s/\à/à/g; s/\à/à/g;
s/\ℵ/x/g; s/\ℵ/x/g;
s/\α/a/g; s/\α/a/g;
s/\∧/&/g; s/\∧/&/g;
s/\∠/</g; s/\∠/</g;
s/\å/å/g; s/\å/å/g;
s/\≈/~/g; s/\≈/~/g;
s/\ã/ã/g; s/\ã/ã/g;
s/\ä/ä/g; s/\ä/ä/g;
s/\„/"/g;s/\„/"/g;
s/\β/ß/g; s/\β/ß/g;
s/\¦/|/g; s/\¦/|/g;
s/\•/·/g; s/\•/·/g;
s/\∩/cap/g; s/\∩/cap/g;
s/\ç/ç/g; s/\ç/ç/g;
s/\¸/,/g; s/\¸/,/g;
s/\¢/¢/g; s/\¢/¢/g;
s/\χ/æ/g; s/\χ/æ/g;
s/\ˆ/^/g; s/\ˆ/^/g;
s/\♣/*/g; s/\♣/*/g;
s/\≅/~=/g; s/\≅/~=/g;
s/\©/(c)/g; s/\©/(c)/g;
s/\↵/<-|/g;s/\↵/<-|/g;
s/\∪/u/g; s/\∪/u/g;
s/\¤/¤/g; s/\¤/¤/g;
s/\⇓/V/g; s/\⇓/V/g;
s/\†/+/g; s/\†/+/g;
s/\↓/v/g; s/\↓/v/g;
s/\°/°/g; s/\°/°/g;
s/\δ/ð/g; s/\δ/ð/g;
s/\♦/#/g; s/\♦/#/g;
s/\÷/÷/g; s/\÷/÷/g;
s/\é/é/g; s/\é/é/g;
s/\ê/ê/g; s/\ê/ê/g;
s/\è/è/g; s/\è/è/g;
s/\∅/ø/g; s/\∅/ø/g;
s/\ / /g; s/\ / /g;
s/\ / /g; s/\ / /g;
s/\ε/e/g; s/\ε/e/g;
s/\≡/=/g; s/\≡/=/g;
s/\η/n/g; s/\η/n/g;
s/\ð/ô/g; s/\ð/ô/g;
s/\ë/ë/g; s/\ë/ë/g;
s/\€/¤/g; s/\€/¤/g;
s/\∃/E/g; s/\∃/E/g;
s/\ƒ/f/g; s/\ƒ/f/g;
s/\∀/V/g; s/\∀/V/g;
s/\½/1\/2/g; s/\½/1\/2/g;
s/\¼/1\/4/g; s/\¼/1\/4/g;
s/\¾/3\/4/g; s/\¾/3\/4/g;
s/\⁄/\//g; s/\⁄/\//g;
s/\γ/y/g; s/\γ/y/g;
s/\≥/>=/g; s/\≥/>=/g;
s/\⇔/<=>/g;s/\⇔/<=>/g;
s/\↔/<->/g;s/\↔/<->/g;
s/\♥/V/g; s/\♥/V/g;
s/\…/.../g; s/\…/.../g;
s/\í/í/g; s/\í/í/g;
s/\î/î/g; s/\î/î/g;
s/\¡/¡/g; s/\¡/¡/g;
s/\ì/ì/g; s/\ì/ì/g;
s/\ℑ/I/g; s/\ℑ/I/g;
s/\∞/oo/g; s/\∞/oo/g;
s/\∫/f/g; s/\∫/f/g;
s/\ι/i/g; s/\ι/i/g;
s/\¿/¿/g; s/\¿/¿/g;
s/\∈/E/g; s/\∈/E/g;
s/\ï/ï/g; s/\ï/ï/g;
s/\κ/k/g; s/\κ/k/g;
s/\⇐/<=/g; s/\⇐/<=/g;
s/\λ/l/g; s/\λ/l/g;
s/\〈/</g; s/\〈/</g;
s/\«/«/g; s/\«/«/g;
s/\»/»/g; s/\»/»/g;
s/\←/<-/g; s/\←/<-/g;
s/\⌈/|-/g; s/\⌈/|-/g;
s/\“/"/g;s/\“/"/g;
s/\≤/<=/g; s/\≤/<=/g;
s/\⌊/|_/g; s/\⌊/|_/g;
s/\∗/*/g; s/\∗/*/g;
s/\◊/<>/g;s/\◊/<>/g;
s/\/<-->/g;s/\/<-->/g;
s/\‹/</g; s/\‹/</g;
s/\‘/'/g;s/\‘/'/g;
s/\¯/'/g; s/\¯/'/g;
s/\—/-/g; s/\—/-/g;
s/\µ/µ/g; s/\µ/µ/g;
s/\·/·/g; s/\·/·/g;
s/\−/-/g; s/\−/-/g;
s/\μ/µ/g; s/\μ/µ/g;
s/\∇/V/g; s/\∇/V/g;
s/\ / /g; s/\ / /g;
s/\–/-/g; s/\–/-/g;
s/\≠/!=/g; s/\≠/!=/g;
s/\∋/E/g; s/\∋/E/g;
s/\¬/¬/g; s/\¬/¬/g;
s/\∉/¬E/g; s/\∉/¬E/g;
s/\⊄/¬</g; s/\⊄/¬</g;
s/\ñ/ñ/g; s/\ñ/ñ/g;
s/\ν/v/g; s/\ν/v/g;
s/\ó/ó/g; s/\ó/ó/g;
s/\ô/ô/g; s/\ô/ô/g;
s/\œ/½/g; s/\œ/½/g;
s/\ò/ò/g; s/\ò/ò/g;
s/\‾/'/g; s/\‾/'/g;
s/\ω/w/g; s/\ω/w/g;
s/\ο/o/g; s/\ο/o/g;
s/\⊕/(+)/g; s/\⊕/(+)/g;
s/\∨/v/g; s/\∨/v/g;
s/\ª/ª/g; s/\ª/ª/g;
s/\º/º/g; s/\º/º/g;
s/\ø/ø/g; s/\ø/ø/g;
s/\õ/ô/g; s/\õ/ô/g;
s/\⊗/(x)/g; s/\⊗/(x)/g;
s/\ö/ö/g; s/\ö/ö/g;
s/\¶/¶/g; s/\¶/¶/g;
s/\∂/a/g; s/\∂/a/g;
s/\‰/0\/oo/g;s/\‰/0\/oo/g;
s/\⊥/^/g; s/\⊥/^/g;
s/\φ/phi/g; s/\φ/phi/g;
s/\π/pi/g; s/\π/pi/g;
s/\ϖ/piv/g; s/\ϖ/piv/g;
s/\±/±/g; s/\±/±/g;
s/\£/£/g; s/\£/£/g;
s/\′/'/g; s/\′/'/g;
s/\∏/|'|/g; s/\∏/|'|/g;
s/\∝/~/g; s/\∝/~/g;
s/\ψ/V/g; s/\ψ/V/g;
s/\⇒/=>/g; s/\⇒/=>/g;
s/\√/sqrt/g; s/\√/sqrt/g;
s/\〉/>/g; s/\〉/>/g;
s/\⌉/'|/g; s/\⌉/'|/g;
s/\”/"/g;s/\”/"/g;
s/\ℜ/R/g; s/\ℜ/R/g;
s/\®/®/g; s/\®/®/g;
s/\⌋/_|/g; s/\⌋/_|/g;
s/\ρ/p/g; s/\ρ/p/g;
s/\/<->/g;s/\/<->/g;
s/\›/>/g; s/\›/>/g;
s/\’/'/g; s/\’/'/g;
s/\‚/,/g; s/\‚/,/g;
s/\š/¦/g; s/\š/¦/g;
s/\⋅/·/g; s/\⋅/·/g;
s/\§/§/g; s/\§/§/g;
s/\/-/g; s/\/-/g;
s/\σ/o/g; s/\σ/o/g;
s/\ς/l/g; s/\ς/l/g;
s/\∼/~/g; s/\∼/~/g;
s/\♠/*/g; s/\♠/*/g;
s/\⊂/sub/g; s/\⊂/sub/g;
s/\⊆/sub=/g; s/\⊆/sub=/g;
s/\∑/E/g; s/\∑/E/g;
s/\¹/¹/g; s/\¹/¹/g;
s/\²/²/g; s/\²/²/g;
s/\³/³/g; s/\³/³/g;
s/\⊃/sup/g; s/\⊃/sup/g;
s/\⊇/sup=/g; s/\⊇/sup=/g;
s/\ß/ß/g; s/\ß/ß/g;
s/\τ/t/g; s/\τ/t/g;
s/\∴/:=/g; s/\∴/:=/g;
s/\θ/Ø/g; s/\θ/Ø/g;
s/\ϑ/v/g; s/\ϑ/v/g;
s/\ / /g; s/\ / /g;
s/\þ/þ/g; s/\þ/þ/g;
s/\˜/~/g; s/\˜/~/g;
s/\×/x/g; s/\×/x/g;
s/\™/(TM)/g; s/\™/(TM)/g;
s/\⇑/^/g; s/\⇑/^/g;
s/\ú/ú/g; s/\ú/ú/g;
s/\↑/^/g; s/\↑/^/g;
s/\û/û/g; s/\û/û/g;
s/\ù/ù/g; s/\ù/ù/g;
s/\¨/"/g; s/\¨/"/g;
s/\ϒ/Y/g; s/\ϒ/Y/g;
s/\υ/y/g; s/\υ/y/g;
s/\ü/ü/g; s/\ü/ü/g;
s/\℘/P/g; s/\℘/P/g;
s/\ξ/x/g; s/\ξ/x/g;
s/\ý/ý/g; s/\ý/ý/g;
s/\¥/¥/g; s/\¥/¥/g;
s/\ÿ/ÿ/g; s/\ÿ/ÿ/g;
s/\ζ/z/g; s/\ζ/z/g;
s/\//g; s/\//g;
s/\//g; s/\//g;
return $_;
}