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>... // 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\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 = "\"$alt\"
\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); } // ---------------------------------------------------------- ?>