text
// added pull of contents from links in feed to fill out the
// missing description fields from the feeds.
// rss-mesoscale-test.php Version 1.00 - 18-Aug-2006
// adapted to handle RSS from the Storm Prediction Center
// mesoscale discussions.
// rss-mesoscale-test.php Version 1.01 - 19-Aug-2006 -- added pull text/image
// to function
// Version 2.00 - 23-Jun-2018 - use curl to fetch https from SPC site
$Version = "V2.00 23-Jun-2018";
//error_reporting(E_ALL ^ E_NOTICE);
//error_reporting(E_ALL);
if (!isset($PHP_SELF)) {$PHP_SELF = $_SERVER['SCRIPT_NAME']; }
//
// script available at http://saratoga-weather.org/scripts.php
//
// you may copy/modify/use this script as you see fit,
// no warranty is expressed or implied.
//
// This script gets the current RSS Mesoscale Discussions
// from http://www.spc.noaa.gov/products/spcmdrss.xml and provides either
// a summary (titles only, with links) or details. It returns
//'No Mesoscale Discussions are in effect as of Day, Mon dd, yyyy hh:mm:ss UTC'
// if there are no current discussions.
//
// output: creates XHTML 1.0-Strict HTML page (default)
//
// Options on URL:
// inc=Y -- returns only the body code for inclusion
// in other webpages. Omit to return full HTML.
// summary=Y -- returns only the titles of the cited discussions
//
// example URL:
// http://your.website/rss-mesoscale-test.php?inc=Y
// would return data without HTML header/footer
//
// Usage:
// you can use this webpage standalone (customize the HTML portion below)
// or you can include it in an existing page:
// no parms: include("rss-mesoscale-test.php");
// parms: include("http://your.website/rss-mesoscale-test.php?inc=Y&summary=Y");
//
//
// settings:
// other settings are outlined below, and are optional
//
// settings ----------------------------------------------------------
$hurlURL = "$PHP_SELF"; // <=== change this default to webpage
// to open for details
// on that page, you can have the following PHP
//
// include("http://your.website/rss-mesoscale-test.php?inc=Y");
//
//
//
$HD = "h2"; // <=== type of heading for advisorys <$HD>...$HD>
// end of settings -------------------------------------------------
$RSSURL = 'https://www.spc.noaa.gov/products/spcmdrss.xml';
// get request parameters
// full html output or just contents (inc=Y)?
if ( ! isset($_REQUEST['inc']) ) {
$_REQUEST['inc']="";
}
$includeOnly = $_REQUEST['inc']; // any nonblank is ok
if ($includeOnly) {$includeOnly = "Y";}
if ( isset($_REQUEST['summary'])) {
$doSummary = TRUE;
} else {
$doSummary = FALSE;
}
// the following is another way to pass the name of the page for testing
if (isset($_REQUEST['detailpage']) ) {
$hurlURL = $_REQUEST['detailpage'];
}
if (isset($_REQUEST['sce']) and $_REQUEST['sce'] == 'view' ) {
//--self downloader --
$filenameReal = __FILE__;
$download_size = filesize($filenameReal);
header('Pragma: public');
header('Cache-Control: private');
header('Cache-Control: no-cache, must-revalidate');
header("Content-type: text/plain");
header("Accept-Ranges: bytes");
header("Content-Length: $download_size");
header('Connection: close');
readfile($filenameReal);
exit;
}
// begin code -----------------------------------------------------------
$t = pathinfo($PHP_SELF);
$Program = $t['basename'];
$insideitem = false;
$tag = "";
$title = "";
$description = "";
$link = "";
$lastBuildDate = "";
$tracking = "";
$Summary = "";
$WLink = 0;
$PageTitle = "";
$Status = '';
$forceHTTPS = (strpos($RSSURL,'https:') !== false)?'https':'http';
global $Status,$forceHTTPS;
// function for XML parsing .. invoked at start of XML element
function startElement($parser, $name, $attrs) {
global $insideitem, $tag, $title, $description, $link, $lastBuildDate,$doSummary,$Summary, $PageTitle;
if ($insideitem) {
$tag = $name;
} elseif ($name == "ITEM") {
$insideitem = true;
}
if ($name == "LASTBUILDDATE") {
$tag = $name;
}
}
// function for XML parsing .. invoked at end of XML element
// bulk of the work is done here
function endElement($parser, $name) {
global $insideitem, $tag, $title, $description, $link, $lastBuildDate, $tracking,$doSummary,$Summary,$Zone,$hurlURL,$WLink,$HD, $PageTitle,$forceHTTPS;
if ($name == "ITEM") {
if (preg_match("|No Mesoscale Discussions are in effect|i",$description)) {
if (! $doSummary) {
printf("%s",htmlspecialchars(trim($description)));
}
$Summary = htmlspecialchars(trim($description));
} else {
$WLink++;
$description = preg_replace("|
|s","
\n",$description);
$description = preg_replace("|href=http([^>]+)>|is","href=\"$forceHTTPS\\1\">",$description);
$description = str_replace('http:',"$forceHTTPS:",$description);
$link = str_replace('http:',"$forceHTTPS:",$link);
if (! $doSummary) {
printf("<$HD>\n%s$HD>\n",
trim($link),htmlspecialchars(trim($title)));
// printf("
Updated: %s
\n
%s
\n", $lastBuildDate,trim($description));
print "\n";
if (strlen($description) < 200 ) {
printf("%s
\n",trim($description));
$text = grabContents($link);
print "\n";
print "\n$text
\n";
} else {
$nl = strpos($description,"\n");
print "\n";
if ($nl >= 80) {
printf("%s
\n",trim($description));
} else {
printf("%s
\n",trim($description));
}
}
}
$Summary .= "" .
htmlspecialchars(trim($title)) . "
\n";
}
$title = "";
$description = "";
$link = "";
$insideitem = false;
} // end insideitem
if ($name == "LASTBUILDDATE") {
$tag = '';
}
$tracking .= "\n";
}
// extract character data from within an XML tag
function characterData($parser, $data) {
global $insideitem, $tag, $title, $description, $link, $lastBuildDate,$doSummary,$Summary, $PageTitle,$forceHTTPS;
if ($tag == "LASTBUILDDATE") {
$lastBuildDate .= $data;
}
if ($tag == 'TITLE' and (! $insideitem) ) {
$PageTitle .= $data;
}
if ($insideitem) {
switch ($tag) {
case "TITLE":
$title .= $data;
break;
case "DESCRIPTION":
$description .= $data;
break;
case "LINK":
$link .= $data;
break;
} // end switch
} // end insideitem
}
// Main Code Start
if (! $includeOnly) { // omit HTML headers if doing inc=Y
print '
RSS Mesoscale Discussions from Storm Prediction Center
';
} // end .. only printed if full html needed
print "\n";
print "\n";
print "\n";
// main routine -- get RSS, parse and display
// adapted from SitePoint sample code at:
// http://www.sitepoint.com/examples/phpxml/sitepointcover.php.txt and article at
// http://www.sitepoint.com/article/php-xml-parsing-rss-1-0
// by Ken True -- webmaster@saratoga-weather.org
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
$rawXML = SPC_fetchUrlWithoutHanging($RSSURL,false);
print $Status;
list($header,$data) = explode("\r\n\r\n",$rawXML);
xml_parse($xml_parser, $data, true)
or die(sprintf("%s XML error: %s at line %d: %s",
$PHP_SELF,
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser),
htmlspecialchars(trim($data)) ));
// end of main program
if ($doSummary) {
print $Summary;
if ($WLink) {
print "Click on link";
if ($WLink > 1) {echo "s";}
print " above to see details on the $WLink Storm Prediction Center discussion";
if ($WLink > 1) {echo "s"; } else { echo ""; };
echo ".\n";
}
}
if (! $includeOnly) {
//print "\n\n";
//print $tracking;
print '
';
} // end - only printed if full html wanted (no inc=Y)
// ----------------------------functions -----------------------------------
function grabContents($dataURL) {
$URL = trim($dataURL);
$URLparts = parse_url($URL);
$PATHparts = pathinfo($URLparts['path']);
print "\n";
$html = SPC_fetchUrlWithoutHanging($URL,false);
print $Status;
print "\n";
preg_match('|(.*)|Uis',$html,$stuff);
$contents = $stuff[1];
preg_match('|
|Uis',$contents,$stuff);
$img = $stuff[1];
$alt = $stuff[2];
$htmlfile = $PATHparts['basename'];
$imgURL = str_replace($htmlfile,$img,$URL);
$imgURL = str_replace('http://www.spc.noaa.gov','https://www.spc.noaa.gov',$imgURL); // force HTTPS on image
print "\n";
preg_match('|(.*)
|Uis',$contents,$stuff);
$contentraw = $stuff[1];
// $content = explode("\n",$contentraw);
// print "";
$imgString = "
\n";
return ($imgString . trim($contentraw) );
}
function SPC_fetchUrlWithoutHanging($url,$useFopen) {
// get contents from one URL and return as string
global $Status, $needCookie;
$overall_start = time();
if (! $useFopen) {
// Set maximum number of seconds (can have floating-point) to wait for feed before displaying page without feed
$numberOfSeconds=6;
// Thanks to Curly from ricksturf.com for the cURL fetch functions
$data = '';
$domain = parse_url($url,PHP_URL_HOST);
$theURL = str_replace('nocache','?'.$overall_start,$url); // add cache-buster to URL if needed
$Status .= "\n";
$ch = curl_init(); // initialize a cURL session
curl_setopt($ch, CURLOPT_URL, $theURL); // connect to provided URL
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // don't verify peer certificate
curl_setopt($ch, CURLOPT_USERAGENT,
'Mozilla/5.0 (rss-mesoscale-test.php - saratoga-weather.org)');
curl_setopt($ch,CURLOPT_HTTPHEADER, // request LD-JSON format
array (
"Accept: text/html,text/plain"
));
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $numberOfSeconds); // connection timeout
curl_setopt($ch, CURLOPT_TIMEOUT, $numberOfSeconds); // data timeout
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // return the data transfer
curl_setopt($ch, CURLOPT_NOBODY, false); // set nobody
curl_setopt($ch, CURLOPT_HEADER, true); // include header information
// curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // follow Location: redirect
// curl_setopt($ch, CURLOPT_MAXREDIRS, 1); // but only one time
if (isset($needCookie[$domain])) {
curl_setopt($ch, $needCookie[$domain]); // set the cookie for this request
curl_setopt($ch, CURLOPT_COOKIESESSION, true); // and ignore prior cookies
$Status .= "\n";
}
$data = curl_exec($ch); // execute session
if(curl_error($ch) <> '') { // IF there is an error
$Status .= "\n"; // display error notice
}
$cinfo = curl_getinfo($ch); // get info on curl exec.
/*
curl info sample
Array
(
[url] => http://saratoga-weather.net/clientraw.txt
[content_type] => text/plain
[http_code] => 200
[header_size] => 266
[request_size] => 141
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.125
[namelookup_time] => 0.016
[connect_time] => 0.063
[pretransfer_time] => 0.063
[size_upload] => 0
[size_download] => 758
[speed_download] => 6064
[speed_upload] => 0
[download_content_length] => 758
[upload_content_length] => -1
[starttransfer_time] => 0.125
[redirect_time] => 0
[redirect_url] =>
[primary_ip] => 74.208.149.102
[certinfo] => Array
(
)
[primary_port] => 80
[local_ip] => 192.168.1.104
[local_port] => 54156
)
*/
$Status .= "\n";
//$Status .= "\n";
curl_close($ch); // close the cURL session
//$Status .= "\n";
$i = strpos($data,"\r\n\r\n");
$headers = substr($data,0,$i);
$content = substr($data,$i+4);
if($cinfo['http_code'] <> '200') {
$Status .= "\n";
}
return $data; // return headers+contents
} else {
// print "\n";
$STRopts = array(
'http'=>array(
'method'=>"GET",
'protocol_version' => 1.1,
'header'=>"Cache-Control: no-cache, must-revalidate\r\n" .
"Cache-control: max-age=0\r\n" .
"Connection: close\r\n" .
"User-agent: Mozilla/5.0 (rss-mesoscale-test.php - saratoga-weather.org)\r\n" .
"Accept: text/html,text/plain\r\n"
),
'https'=>array(
'method'=>"GET",
'protocol_version' => 1.1,
'header'=>"Cache-Control: no-cache, must-revalidate\r\n" .
"Cache-control: max-age=0\r\n" .
"Connection: close\r\n" .
"User-agent: Mozilla/5.0 (rss-mesoscale-test.php - saratoga-weather.org)\r\n" .
"Accept: text/html,text/plain\r\n"
)
);
$STRcontext = stream_context_create($STRopts);
$T_start = SPC_fetch_microtime();
$xml = file_get_contents($url,false,$STRcontext);
$T_close = SPC_fetch_microtime();
$headerarray = get_headers($url,0);
$theaders = join("\r\n",$headerarray);
$xml = $theaders . "\r\n\r\n" . $xml;
$ms_total = sprintf("%01.3f",round($T_close - $T_start,3));
$Status .= "\n";
$Status .= "<-- get_headers returns\n".$theaders."\n -->\n";
// print " file() stats: total=$ms_total secs.\n";
$overall_end = time();
$overall_elapsed = $overall_end - $overall_start;
$Status .= "\n";
// print "fetch function elapsed= $overall_elapsed secs.\n";
return($xml);
}
} // end SPC_fetchUrlWithoutHanging
// ------------------------------------------------------------------
function SPC_fetch_microtime()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
// ----------------------------------------------------------
?>