and Short legend. // $WCforecastthunder[$i] - thunder risk (text) // $WCforecastuv[$i] - formatted UVIndex and word description // $WCforecastsnow[$i] - amount of snow forecast (or empty if no snow) // $WCforecastrain[$i] - amount of rain forecast (or empty if no rain) // // // Settings --------------------------------------------------------------- //REQUIRED: a WU API KEY.. sign up at https://www.wunderground.com/member/api-keys $WCAPIkey = 'specify-for-standalone-use-here'; // use this only for standalone / non-template use // NOTE: if using the Saratoga template, add to Settings.php a line with: // $SITE['WCAPIkey'] = 'your-api-key-here'; // and that will enable the script to operate correctly in your template // // Select which units will be used for the displays: // //$WCunits = 'e'; // 'e'= US units F,mph,inHg,in,in $WCunits = 'm'; // 'm'= metric C,km/h,hPa,mm,cm //$WCunits = 'h'; // 'h'= UK units C,mph,mb,mm,cm //$WCunits = 's'; // 's'= SI units C,m/s,hPa,mm,cm // $iconDir ='./forecast/images/'; // directory for carterlake icons './forecast/images/' $iconType = '.jpg'; // default type='.jpg' // use '.gif' for animated icons from http://www.meteotreviglio.com/ // // $WC_LOC = 'Saratoga, CA, USA|37.27465,-122.02295'; // // The optional multi-city forecast .. make sure the first entry is for the $WC_LOC location // The contents will be replaced by $SITE['WCforecasts'] if specified in your Settings.php //* $WCforecasts = array( // Location name to display|lat,long (separated by | character) 'Saratoga, CA, USA|37.27465,-122.02295', 'Auckland, NZ|-36.910,174.771', // Awhitu, Waiuku New Zealand 'Assen, NL|53.02277,6.59037', 'Blankenburg, DE|51.8089941,10.9080649', 'Cheyenne, WY, USA|41.144259,-104.83497', 'Carcassonne, FR|43.2077801,2.2790407', 'Braniewo, PL|54.3793635,19.7853585', 'Omaha, NE, USA|41.19043,-96.13114', 'Johanngeorgenstadt, DE|50.439339,12.706085', 'Athens, GR|37.97830,23.715363', 'Haifa, IL|32.7996029,34.9467358', 'Tahoe Vista, CA, USA|39.2403,-120.0528', 'Auburn, CA, USA|38.8962,-121.0789', ); //*/ $commaDecimal = false; // set to true to process numbers with a comma for a decimal point // $maxWidth = '640px'; // max width of tables (could be '100%') $maxForecastLegendWords = 4; // more words in forecast legend than this number will use our forecast words $autoSetTemplate = true; // =true; set icons based on wide/narrow template design // // =false; don't autoset maxWidth based on Saratoga wide/narrow $foldIconRow = true; // =true; display icons in rows of 5 if long texts are found $iconRowDayNight = true; // =false; 9 icons in a row, folded over if long texts. // // =true; icons always in two rows Day over Night $cacheFileDir = './'; // default cache file directory $cacheName = "WC-forecast-json.txt"; // locally cached page from WC $refetchSeconds = 3600; // cache lifetime (3600sec = 60 minutes) $charsetOutput = 'ISO-8859-1'; // default character encoding of output ='ISO-8859-1' for Saratoga templates $lang = 'en'; // default language ='en' for English // ---- end of settings --------------------------------------------------- // overrides from Settings.php if available global $SITE; if (isset($SITE['WCforecasts'])) {$WCforecasts = $SITE['WCforecasts']; } if (isset($SITE['WCAPIkey'])) {$WCAPIkey = $SITE['WCAPIkey']; } if (isset($SITE['WCunits'])) {$WCunits = $SITE['WCunits']; } if (isset($SITE['fcsturlWC'])) {$WC_LOC = $SITE['fcsturlWC'];} if (isset($SITE['fcsticonsdir'])) {$iconDir = $SITE['fcsticonsdir'];} if (isset($SITE['fcsticonstype'])) {$iconType = $SITE['fcsticonstype'];} if (isset($SITE['charset'])) {$charsetOutput = strtoupper($SITE['charset']); } if (isset($SITE['lang'])) {$lang = $SITE['lang'];} if(isset($SITE['cacheFileDir'])) {$cacheFileDir = $SITE['cacheFileDir']; } if(isset($SITE['foldIconRow'])) {$foldIconRow = $SITE['foldIconRow']; } if(isset($SITE['iconRowDayNight'])) {$iconRowDayNight = $SITE['iconRowDayNight']; } if(isset($SITE['RTL-LANG'])) {$RTLlang = $SITE['RTL-LANG']; } if (isset($SITE['commaDecimal'])) {$commaDecimal = $SITE['commaDecimal'];} // end of overrides from Settings.php // // -------------------begin code ------------------------------------------ if (isset($_REQUEST['sce']) && strtolower($_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;charset=ISO-8859-1"); header("Accept-Ranges: bytes"); header("Content-Length: $download_size"); header('Connection: close'); readfile($filenameReal); exit; } $Status = "\n"; //------------------------------------------------ if(preg_match('|specify|i',$WCAPIkey)) { print "

Note: the WC-forecast.php script requires an API key from WeatherUnderground to operate.
"; print "Visit Weather Underground to "; print "register for an API key. You must have a PWS submitting data to WU to acquire an API key.

\n"; if( isset($SITE['fcsturlWC']) ) { print "

Insert in Settings.php an entry for:

\n"; print "\$SITE['WCAPIkey'] = 'your-key-here';

\n"; print "replacing your-key-here with your WU/TWC API key.

\n"; } return; } $NWSiconlist = array( // translation from api.weather.gov icons to NWS-styled icons Day,Night 0 => array('tor.jpg','ntor.jpg'), // Tornado, 00.png, Forecast, Night + Day 1 => array('tropstorm-noh.jpg','tropstorm-noh.jpg'), // Tropical Storm, 01.png, Forecast + Observations, Night + Day 2 => array('hurr-noh.jpg','hurr-noh.jpg'), // Hurricane, 02.png, Forecast, Night + Day 3 => array('scttsra.jpg','nscttsra.jpg'), // Strong Storms, 03.png, Forecast, Night + Day 4 => array('tsra.jpg','ntsra.jpg'), // Thunder and Hail, 04.png, Forecast + Observations, Night + Day 5 => array('rasn.jpg','nrasn.jpg'), // Rain to Snow Showers, 05.png, Forecast + Observations, Night + Day 6 => array('raip.jpg','nraip.jpg'), // Rain / Sleet, 06.png, Forecast + Observations, Night + Day 7 => array('mix.jpg','nmix.jpg'), // Wintry Mix Snow / Sleet, 07.png, Forecast + Observations, Night + Day 8 => array('fzrara.jpg','fzrara.jpg'), // Freezing Drizzle, 08.png, Forecast + Observations, Night + Day 9 => array('mist.jpg','mist.jpg'), // Drizzle, 09.png, Forecast + Observations, Night + Day 10 => array('fzra.jpg','nfzra.jpg'), // Freezing Rain, 10.png, Forecast + Observations, Night + Day 11 => array('ra.jpg','nra.jpg'), // Light Rain, 11.png, Forecast + Observations, Night + Day 12 => array('ra.jpg','nra.jpg'), // Rain, 12.png, Forecast + Observations, Night + Day 13 => array('sn.jpg','nsn.jpg'), // Scattered Flurries, 13.png, Forecast + Observations, Night + Day 14 => array('sn.jpg','nsn.jpg'), // Light Snow, 14.png, Forecast + Observations, Night + Day 15 => array('blizzard.jpg','nblizzard.jpg'), // Blowing / Drifting Snow, 15.png, Forecast + Observations, Night + Day 16 => array('sn.jpg','nsn.jpg'), // Snow, 16.png, Forecast + Observations, Night + Day 17 => array('ip.jpg','nip.jpg'), // Hail, 17.png, Forecast + Observations, Night + Day 18 => array('ip.jpg','nip.jpg'), // Sleet, 18.png, Forecast + Observations, Night + Day 19 => array('du.jpg','ndu.jpg'), // Blowing Dust / Sandstorm, 19.png, Forecast + Observations, Night + Day 20 => array('fg.jpg','nfg.jpg'), // Foggy, 20.png, Forecast + Observations, Night + Day 21 => array('hazy.jpg','hazy.jpg'), // Haze / Windy, 21.png, Forecast + Observations, Night + Day 22 => array('fu.jpg','nfu.jpg'), // Smoke / Windy, 22.png, Forecast + Observations, Night + Day 23 => array('wind.jpg','nwind.jpg'), // Breezy, 23.png, Forecast, Night + Day 24 => array('wind.jpg','nwind.jpg'), // Blowing Spray / Windy, 24.png, Forecast + Observations, Night + Day 25 => array('cold.jpg','ncold.jpg'), // Frigid / Ice Crystals, 25.png, Forecast + Observations, Night + Day 26 => array('ovc.jpg','novc.jpg'), // Cloudy, 26.png, Forecast + Observations, Night + Day 27 => array('bkn.jpg','nbkn.jpg'), // Mostly Cloudy, 27.png, Forecast + Observations, Night + Day 28 => array('bkn.jpg','nbkn.jpg'), // Mostly Cloudy, 28.png, Forecast + Observations, Day 29 => array('sct.jpg','nsct.jpg'), // Partly Cloudy, 29.png, Forecast + Observations, Night 30 => array('sct.jpg','nsct.jpg'), // Partly Cloudy, 30.png, Forecast + Observations, Day 31 => array('skc.jpg','nskc.jpg'), // Clear, 31.png, Forecast + Observations, Night 32 => array('skc.jpg','nskc.jpg'), // Sunny, 32.png, Forecast + Observations, Day 33 => array('few.jpg','nfew.jpg'), // Fair / Mostly Clear, 33.png, Forecast + Observations, Night 34 => array('few.jpg','nfew.jpg'), // Fair / Mostly Sunny, 34.png, Forecast + Observations, Day 35 => array('raip.jpg','nraip.jpg'), // Mixed Rain & Hail, 35.png, Forecast, Day 36 => array('hot.jpg','hot.jpg'), // Hot, 36.png, Forecast, Day 37 => array('scttsra.jpg','nscttsra.jpg'), // Isolated Thunderstorms, 37.png, Forecast, Day 38 => array('tsra.jpg','ntsra.jpg'), // Thunderstorms, 38.png, Forecast + Observations, Night + Day 39 => array('hi_shwrs.jpg','hi_nshwrs.jpg'), // Scattered Showers, 39.png, Forecast, Day 40 => array('shra.jpg','nshra.jpg'), // Heavy Rain, 40.png, Forecast + Observations, Night + Day 41 => array('sn.jpg','nsn.jpg'), // Scattered Snow Showers, 41.png, Forecast, Day 42 => array('sn.jpg','nsn.jpg'), // Heavy Snow, 42.png, Forecast + Observations, Night + Day 43 => array('blizzard.jpg','nblizzard.jpg'), // Blizzard, 43.png, Forecast, Night + Day 44 => array('na.jpg','na.jpg'), // Not Available (N/A), 44.png, Forecast, Night + Day 45 => array('hi_shwrs.jpg','hi_nshwrs.jpg'), // Scattered Showers, 45.png, Forecast, Night 46 => array('sn.jpg','nsn.jpg'), // Scattered Snow Showers, 46.png, Forecast, Night 47 => array('scttsra.jpg','nscttsra.jpg'), // Scattered Thunderstorms, 47.png, Forecast + Observations, Night + Day ) ; //*/ if(!function_exists('langtransstr')) { // shim function if not running in template set function langtransstr($input) { return($input); } } if(!function_exists('json_last_error')) { // shim function if not running PHP 5.3+ function json_last_error() { return('- N/A'); } $Status .= "\n"; if(!defined('JSON_ERROR_NONE')) { define('JSON_ERROR_NONE',0); } if(!defined('JSON_ERROR_DEPTH')) { define('JSON_ERROR_DEPTH',1); } if(!defined('JSON_ERROR_STATE_MISMATCH')) { define('JSON_ERROR_STATE_MISMATCH',2); } if(!defined('JSON_ERROR_CTRL_CHAR')) { define('JSON_ERROR_CTRL_CHAR',3); } if(!defined('JSON_ERROR_SYNTAX')) { define('JSON_ERROR_SYNTAX',4); } if(!defined('JSON_ERROR_UTF8')) { define('JSON_ERROR_UTF8',5); } } WC_loadLangDefaults (); // set up the language defaults $WCLANG = 'en-US'; // Default to English for API $RTLlang = ',he,jp,cn,'; // languages that use right-to-left order $lang = strtolower($lang); if(isset($WClanguages[$lang]) ) { // if $lang is specified, use it $SITE['lang'] = $lang; $WCLANG = $WClanguages[$lang]; if($charsetOutput !== 'UTF-8') { $charsetOutput = (isset($WClangCharsets[$lang]))?$WClangCharsets[$lang]:$charsetOutput; } } if(isset($_GET['lang']) and isset($WClanguages[strtolower($_GET['lang'])]) ) { // template override $lang = strtolower($_GET['lang']); $SITE['lang'] = $lang; $WCLANG = $WClanguages[$lang]; if($charsetOutput !== 'UTF-8') { $charsetOutput = (isset($WClangCharsets[$lang]))?$WClangCharsets[$lang]:$charsetOutput; } } $doRTL = (strpos($RTLlang,$lang) !== false)?true:false; // format RTL language in Right-to-left in output // get the selected forecast location code $haveIndex = '0'; if (!empty($_GET['z']) && preg_match("/^[0-9]+$/i", htmlspecialchars($_GET['z']))) { $haveIndex = htmlspecialchars(strip_tags($_GET['z'])); // valid zone syntax from input } if(!isset($WCforecasts[0])) { // print "\n"; $WCforecasts = array("$WC_LOC"); // create default entry } // print "\n"; // Set the default zone. The first entry in the $SITE['NWSforecasts'] array. list($Nl,$Nn) = explode('|',$WCforecasts[0].'|||'); $FCSTlocation = $Nl; $WC_LOC = $Nn; if(!isset($WCforecasts[$haveIndex])) { $haveIndex = 0; } // locations added to the drop down menu and set selected zone values $dDownMenu = ''; for ($m=0;$m".langtransstr($Nlocation)."\n"; } // build the drop down menu $ddMenu = ''; // create menu if at least two locations are listed in the array if (isset($WCforecasts[0]) and isset($WCforecasts[1])) { if($doRTL) {$RTLopt = ' style="direction: rtl;"'; } else {$RTLopt = '';}; $ddMenu .= '

'; } $Force = false; if (isset($_REQUEST['force']) and $_REQUEST['force']=="1" ) { $Force = true; } $doDebug = false; if (isset($_REQUEST['debug']) and strtolower($_REQUEST['debug'])=='y' ) { $doDebug = true; } $fileName = $WC_LOC; if ($doDebug) { $Status .= "\n"; } if ($autoSetTemplate and isset($_SESSION['CSSwidescreen'])) { if($_SESSION['CSSwidescreen'] == true) { $maxWidth = '900px'; $Status .= "\n"; } if($_SESSION['CSSwidescreen'] == false) { $maxWidth = '640px'; $Status .= "\n"; } } $cacheName = $cacheFileDir . $cacheName; // unique cache per index:UOM:language used $cacheName = preg_replace('|\.txt|is',"-$haveIndex-$WCunits-$lang.txt",$cacheName); $APIfileName = WC_get_APIURL($fileName); // transform WC page URL to API query URL if (! $Force and file_exists($cacheName) and filemtime($cacheName) + $refetchSeconds > time()) { $html = implode('', file($cacheName)); $Status .= "\n"; } else { $Status .= "\n"; $html = WC_fetchUrlWithoutHanging($APIfileName,false); $RC = ''; if (preg_match("|^HTTP\/\S+ (.*)\r\n|",$html,$matches)) { $RC = trim($matches[1]); } $Status .= "\n"; if (preg_match('|30\d|',$RC)) { // handle possible blocked redirect preg_match('|Location: (\S+)|is',$html,$matches); if(isset($matches[1])) { $sURL = $matches[1]; if(preg_match('|opendns.com|i',$sURL)) { $Status .= "\n"; } else { $Status .= "\n"; $html = WC_fetchUrlWithoutHanging($sURL,false); $RC = ''; if (preg_match("|^HTTP\/\S+ (.*)\r\n|",$html,$matches)) { $RC = trim($matches[1]); } $Status .= "\n"; } } } if(preg_match('|daypart|Uis',$html)) { $fp = fopen($cacheName, "w"); if (!$fp) { $Status .= "\n"; } else { $write = fputs($fp, $html); fclose($fp); $Status .= "\n"; } } elseif (file_exists($cacheName)) { $html = implode('', file($cacheName)); $Status .= "\n"; $Status .= "\n"; } } // establish JSON charset. Usually in UTF-8 preg_match('|charset="{0,1}(\S+)"{0,1}|i',$html,$matches); if (isset($matches[1])) { $charsetInput = strtoupper($matches[1]); } else { $charsetInput = 'UTF-8'; } $doIconv = ($charsetInput == $charsetOutput)?false:true; // only do iconv() if sets are different $Status .= "\n"; $i = strpos($html,"\r\n\r\n"); $headers = substr($html,0,$i-1); $content = substr($html,$i+4); if(preg_match('|Transfer-Encoding: chunke|Ui',$headers)) { $Status .= "\n"; $Status .= "\n"; } // process the file .. select out the 7-day forecast part of the page $UnSupported = false; // -------------------------------------------------------------------------------------------------- $Status .= "\n"; $i = strpos($html,"\r\n\r\n"); $headers = substr($html,0,$i-1); $content = substr($html,$i+4); $rawJSON = $content; $Status .= "\n"; $rawJSON = WC_prepareJSON($rawJSON); $JSON = json_decode($rawJSON,true); // get as associative array $Status .= WC_decode_JSON_error(); if($doDebug) {$Status .= "\n"; } /* //Ken's dump debugging code $Status = htmlentities($Status); $Status = preg_replace("|\n|is","
\n",$Status); print $Status; return; //Ken's dump debugging code */ if(json_last_error() === JSON_ERROR_NONE) { // got good JSON .. process it $UnSupported = false; $WCforecastcity = $FCSTlocation; if($doIconv) {$WCforecastcity = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$WCforecastcity);} if($doDebug) { $Status .= "\n"; } $WCtitle = "5-day Forecast"; if($doDebug) { $Status .= "\n"; } $n = 0; $FCpart = $JSON['daypart'][0]; $showTempsAs = ($WCunits == 'e')?'F':'C'; // process the forecast periods $n = 0; $firstIconPeriod = ''; foreach ($FCpart['temperature'] as $i => $t) { if(empty($FCpart['daypartName'][$i])) { continue; // skip the empty ones if any } if ( $doDebug) { $Status .= "\n"; } $dayOrNight = $FCpart['dayOrNight'][$i]; if($firstIconPeriod == '') { $firstIconPeriod = $dayOrNight; } if($dayOrNight == 'D') { $WCforecasttemp[$n] = "".$t."°$showTempsAs"; } else { $WCforecasttemp[$n] = "".$t."°$showTempsAs"; } $WCforecastday[$n] = trim($FCpart['daypartName'][$i]); if($doIconv) {$WCforecastday[$n] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$WCforecastday[$n]);} $WCforecasttitles[$n] = $WCforecastday[$n]; if ($doDebug) { $Status .= "\n"; } $WCforecasttext[$n] = trim($FCpart['narrative'][$i]); $WCforecasttext[$n] = str_replace("\xc2\xba","\xc2\xb0",$WCforecasttext[$n]); // fix wrong degree symbol if($doIconv) {$WCforecasttext[$n] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$WCforecasttext[$n]);} if ($doDebug) { $Status .= "\n"; } $WCforecastpop[$n] = $FCpart['precipChance'][$i]; if ($doDebug) { $Status .= "\n"; } $WCforecastcond[$n] = $FCpart['wxPhraseLong'][$i]; $WCforecastcond[$n] = str_replace('/',', ',$WCforecastcond[$n]); if($doIconv) {$WCforecastcond[$n] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$WCforecastcond[$n]);} if ($doDebug) { $Status .= "\n"; } $WCforecasticon[$n] = WC_img_replace($FCpart['iconCode'][$i],$dayOrNight,$WCforecastcond[$n],round($WCforecastpop[$n],-1)); // V1.05 fix if ($doDebug) { $Status .= "\n"; } $WCforecasticons[$n] = $WCforecastday[$n] . "
" . $WCforecasticon[$n] . "
" . $WCforecastcond[$n]; if(!empty($FCpart['thunderIndex'][$i]) and !empty($FCpart['thunderCategory'][$i])) { $WCforecastthunder[$n] = '' .$FCpart['thunderCategory'][$i] . ''; if($doIconv) {$WCforecastthunder[$n] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$WCforecastthunder[$n]);} } else { $WCforecastthunder[$n] = ''; } if ($doDebug) { $Status .= "\n"; } if(!empty($FCpart['uvIndex'][$i]) and $FCpart['uvIndex'][$i] > 0) { $WCforecastuv[$n] = 'UV: '. $FCpart['uvIndex'][$i] . '
'. WC_get_uvrange($FCpart['uvIndex'][$i],$FCpart['uvDescription'][$i]); if($doIconv) {$WCforecastuv[$n] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$WCforecastuv[$n]);} } else { $WCforecastuv[$n] = ''; } if ($doDebug) { $Status .= "\n"; } if(!empty($FCpart['snowRange'][$i])) { $WCforecastsnow[$n] = $FCpart['snowRange'][$i]; $WCforecastsnow[$n] .= ($WCunits == 'e')?' in':' cm'; if($doIconv) {$WCforecastsnow[$n] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$WCforecastsnow[$n]);} } else { $WCforecastsnow[$n] = ''; } if ($doDebug) { $Status .= "\n"; } if(!empty($FCpart['qpf'][$i]) and empty($FCpart['snowRange'][$i])) { $WCforecastrain[$n] = $FCpart['qpf'][$i]; if($WCunits !== 'e') {$WCforecastrain[$n] = round($WCforecastrain[$n],1); } if($WCforecastrain[$n] == 0) {$WCforecastrain[$n] = '<1'; } if($commaDecimal) {$WCforecastrain[$n] = str_replace('.',',',$WCforecastrain[$n]); } $WCforecastrain[$n] .= ($WCunits == 'e')?' in':' mm'; if($doIconv) {$WCforecastrain[$n] = iconv($charsetInput,$charsetOutput.'//TRANSLIT',$WCforecastrain[$n]);} } else { $WCforecastrain[$n] = ''; } if ($doDebug) { $Status .= "\n"; } $n++; } // end of process json forecasts } // end got good JSON decode/process // end process JSON style -------------------------------------------------------------------- // All finished with parsing, now prepare to print if(count($WCforecasticons) < 1) { print "Error: no forecast data was found in JSON from api.weather.gov.\n"; return; } $wdth = intval(100/count($WCforecasticons)); $ndays = intval(count($WCforecasticon)/2); $WCtitle = preg_replace('|5|i',$ndays,$WCtitle,1); $doNumIcons = count($WCforecasticons); // establish what we're going to print based on the options set $IncludeMode = false; $PrintMode = true; if (isset($doPrintWC) && ! $doPrintWC ) { print $Status; return; } if (isset($_REQUEST['inc']) && strtolower($_REQUEST['inc']) == 'noprint' ) { print $Status; return; } if (isset($_REQUEST['inc']) && strtolower($_REQUEST['inc']) == 'y') { $IncludeMode = true; } if (isset($doIncludeWC)) { $IncludeMode = $doIncludeWC; } $printHeading = true; $printIcons = true; $printText = true; if (isset($doPrintHeadingWC)) { $printHeading = $doPrintHeadingWC; } if (isset($_REQUEST['heading']) ) { $printHeading = substr(strtolower($_REQUEST['heading']),0,1) == 'y'; } if (isset($doPrintIconsWC)) { $printIcons = $doPrintIconsWC; } if (isset($_REQUEST['icons']) ) { $printIcons = substr(strtolower($_REQUEST['icons']),0,1) == 'y'; } if (isset($doPrintTextWC)) { $printText = $doPrintTextWC; } if (isset($_REQUEST['text']) ) { $printText = substr(strtolower($_REQUEST['text']),0,1) == 'y'; } // ------- now do the actual HTML generation for the page if (! $IncludeMode and $PrintMode) { ?> WeatherUnderground <?php echo $WCtitle . ' - ' . $WCforecastcity; ?> Sorry.. this forecast can not be processed at this time. EONAG ; } if (strlen($WCforecasttext[0])<2 and $PrintMode and ! $UnSupported ) { echo '

Forecast blank? Force Update

'; } if ($PrintMode and ($printHeading or $printIcons)) { ?> array( array(0,1,2,3,4,5,6,7,8) ), // One row (Straight Line) 'TR' => array( array(0,1,2,3,4), array(5,6,7,8,9) ), // Two Rows 'NO' => array( array(-1,1,3,5,7,9), array(0,2,4,6,8,10) ), // Night first icon, Day over Night 'DO' => array( array(0,2,4,6,8,10), array(1,3,5,7,9,11) ) // Day First icon, Day over Night ); // if RTL, reverse 'em all if(isset($SITE['CSSscreen']) and $doRTL) { $doRTL = false; $Status .= "\n"; } if($doRTL) { foreach ($iconOrder as $type => $MO) { foreach ($MO as $row => $cols) { $iconOrder[$type][$row] = array_reverse($iconOrder[$type][$row]); } } } /* just a bit of test code to show how it works print "
\n";
	
	foreach ($iconOrder as $type => $MO) {
		print "--- $type ---\n";
		foreach ($MO as $row => $cols) {
			print "Row: $row ";
			foreach ($cols as $k => $idx) {
				print "($idx) ";
			}
			print " \n";
		}
		print "------------------\n";
	}
	
	print "
\n"; # end of test code //*/ // see if we need to fold the icon rows due to long text length $doFoldRow = false; // don't assume we have to fold the row.. if($foldIconRow) { $iTitleLen =0; $iTempLen = 0; $iCondLen = 0; for($i=0;$i<$doNumIcons;$i++) { $iTitleLen += strlen(strip_tags($WCforecasttitles[$i])); $iCondLen += strlen(strip_tags($WCforecastcond[$i])); $iTempLen += strlen(strip_tags($WCforecasttemp[$i])); } print "\n"; $maxChars = 135; if($iTitleLen >= $maxChars or $iCondLen >= $maxChars or $iTempLen >= $maxChars ) { print "\n"; $doFoldRow = true; } } if(isset($_REQUEST['foldrow']) and $_REQUEST['foldrow'] == 'y') {$doFoldRow = true;} // set the icon display method based on settings $iList = $iconOrder['S']; // assume single row if($doFoldRow) { $iList = $iconOrder['TR']; // folded row } if($iconRowDayNight) { // day-over-night selected $iList = $iconOrder['DO']; // use day-first order; if($firstIconPeriod == 'N') { $iList = $iconOrder['NO']; // use night-first order } } if($doDebug) {print "\n";} $wdth = round(100 / count($iList[0])); // set percentage width for \n"; print "
WeatherUnderground :
elements based on icon display method $blankRow = array_fill(0,10,' 
 '); print "
\n"; print " \n"; // print the icons in the selected order foreach ($iList as $k => $tRow) { WC_printRow($WCforecasttitles,$tRow,'font-size: 8pt;'); WC_printRow($WCforecasticon,$tRow,''); WC_printRow($WCforecastcond,$tRow,''); WC_printRow($WCforecastrain,$tRow,'color: green;'); WC_printRow($WCforecastsnow,$tRow,'color: darkblue;'); WC_printRow($WCforecastthunder,$tRow,''); WC_printRow($WCforecasttemp,$tRow,''); WC_printRow($WCforecastuv,$tRow,''); if(count($iList)>1) { # insert a blank row betweeen icon rows if needed WC_printRow($blankRow,$tRow,''); } } // end of print icons loop ?>

 

\n"; if(!$doRTL) { // normal Left-to-right print " \n"; print " \n"; } else { // print RTL format print " \n"; print " \n"; } print " \n"; } ?>
$WCforecasttitles[$i]
 
$WCforecasttext[$i]$WCforecasttext[$i]$WCforecasttitles[$i]
 

 

'; print langtransstr('WeatherUnderground forecast for'); ?> . '.jpg') { // print credit for .gif icons if used print "
"; print langtransstr('Animated forecast icons courtesy of'); print " www.meteotreviglio.com."; } ?>

\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 (WC-forecast.php - saratoga-weather.org)'); 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 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 (WC-forecast.php - saratoga-weather.org)\r\n" . "Accept: text/plain,text/html\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 (WC-forecast.php - saratoga-weather.org)\r\n" . "Accept: text/plain,text/html\r\n" ) ); $STRcontext = stream_context_create($STRopts); $T_start = WC_fetch_microtime(); $xml = file_get_contents($url,false,$STRcontext); $T_close = WC_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 WC_fetch_URL // ------------------------------------------------------------------ function WC_fetch_microtime() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } // ------------------------------------------------------------------ function WC_img_replace ( $WCimage, $dayOrNight, $WCcondtext,$WCpop) { // // optionally replace the WeatherUnderground icon with an NWS icon instead. // global $NWSiconlist,$iconDir,$iconType,$Status; $dn = ($dayOrNight == 'D')?0:1; $curicon = isset($NWSiconlist[$WCimage][$dn])?$NWSiconlist[$WCimage][$dn]:''; // translated icon (if any) if (!$curicon) { // no change.. use WC icon $timg = sprintf('%.02d',$WCimage).'.png'; return("\"$WCcondtext\""); } if($iconType <> '.jpg') { $curicon = preg_replace('|\.jpg|',$iconType,$curicon); } $Status .= "\n"; return("\"$WCcondtext\""); } // ------------------------------------------------------------------ function WC_prepareJSON($input) { global $Status; //This will convert ASCII/ISO-8859-1 to UTF-8. //Be careful with the third parameter (encoding detect list), because //if set wrong, some input encodings will get garbled (including UTF-8!) list($isUTF8,$offset,$msg) = WC_check_utf8($input); if(!$isUTF8) { $Status .= "\n"; $str = utf8_encode($input); list($isUTF8,$offset,$msg) = WC_check_utf8($str); $Status .= "\n"; } else { $Status .= "\n"; $str = $input; } //Remove UTF-8 BOM if present, json_decode() does not like it. if(substr($str, 0, 3) == pack("CCC", 0xEF, 0xBB, 0xBF)) $str = substr($str, 3); return $str; } // ------------------------------------------------------------------ function WC_check_utf8($str) { // check all the characters for UTF-8 compliance so json_decode() won't choke // Sometimes, an ISO international character slips in the WC text string. $len = strlen($str); for($i = 0; $i < $len; $i++){ $c = ord($str[$i]); if ($c > 128) { if (($c > 247)) return array(false,$i,"c>247 c='$c'"); elseif ($c > 239) $bytes = 4; elseif ($c > 223) $bytes = 3; elseif ($c > 191) $bytes = 2; else return false; if (($i + $bytes) > $len) return array(false,$i,"i+bytes>len bytes=$bytes,len=$len"); while ($bytes > 1) { $i++; $b = ord($str[$i]); if ($b < 128 || $b > 191) return array(false,$i,"128191 b=$b"); $bytes--; } } } return array(true,$i,"Success. Valid UTF-8"); } // end of check_utf8 // ------------------------------------------------------------------ function WC_decode_JSON_error() { $Status = ''; $Status .= "\n"; return($Status); } // ------------------------------------------------------------------ function WC_get_APIURL ($rawLatLong) { global $WCAPIkey,$WCLANG,$WCunits,$Status,$doDebug; // try to generate an API request URL from a WC lat/long $newURL = 'https://api.weather.com/v3/wx/forecast/daily/5day?format=json&units=%s&language=%s&apiKey=%s&geocode=%s'; $newURL = sprintf($newURL,$WCunits,$WCLANG,$WCAPIkey,$rawLatLong); // add the boilerplate stuff $Status .= "\n"; $Status .= "\n"; return($newURL); } // ------------------------------------------------------------------ function WC_loadLangDefaults () { global $WClanguages, $WClangCharsets; /* Languages from https://docs.google.com/document/d/13HTLgJDpsb39deFzk_YCQ5GoGoZCO_cRYzIxbwvgJLI/edit# ar-AE Arabic - (United Arab Emirates) az-AZ Azerbaijani - (Azerbaijan) bg-BG Bulgarian - (Bulgaria) bn-BD Bengali, Bangla - (Bangladesh) bn-IN Bengali, Bangla - (India) bs-BA Bosnian - (Bosnia and Herzegovina) ca-ES Catalan - (Spain) cs-CZ Czech - (Czechia) da-DK Danish - (Denmark) de-DE German - (Germany) el-GR Greek (modern) - (Greece) en-GB English (Great Britain) en-IN English - (India) en-US English - (United States of America) es-AR Spanish - (Argentina) es-ES Spanish - (Spain) es-LA Spanish - (Latin America) es-MX Spanish - (Mexico) es-UN Spanish - (International) es-US Spanish - (United States of America) et-EE Estonian - (Estonia) fa-IR Persian (Farsi) - (Iran) fi-FI Finnish - (Finland) fr-CA French - (Canada) fr-FR French - (France) gu-IN Gujarati - (India) he-IL Hebrew (modern) - (Israel) hi-IN Hindi - (India) hr-HR Croatian - (Croatia) hu-HU Hungarian - (Hungary) in-ID Indonesian - (Indonesia) is-IS Icelandic - (Iceland) it-IT Italian - (Italy) iw-IL Hebrew - (Israel) ja-JP Japanese - (Japan) jv-ID Javanese - (Indonesia) ka-GE Georgian - (Georgia) kk-KZ Kazakh - (Kazakhstan) kn-IN Kannada - (India) ko-KR Korean - (South Korea) lt-LT Lithuanian - (Lithuania) lv-LV Latvian - (Latvia) mk-MK Macedonian - (Macedonia) mn-MN Mongolian - (Mongolia) ms-MY Malay - (Malaysia) nl-NL Dutch - (Netherlands) no-NO Norwegian - (Norway) pl-PL Polish - (Poland) pt-BR Portuguese - (Brazil) pt-PT Portuguese - (Portugal) ro-RO Romanian - (Romania) ru-RU Russian - (Russia) si-LK Sinhalese, Sinhala - (Sri Lanka) sk-SK Slovak - (Slovakia) sl-SI Slovenian - (Slovenia) sq-AL Albanian - (Albania) sr-BA Serbian - (Bosnia and Herzegovina) sr-ME Serbian - (Montenegro) sr-RS Serbian - (Serbia) sv-SE Swedish - (Sweden) sw-KE Swahili - (Kenya) ta-IN Tamil - (India) ta-LK Tamil - (Sri Lanka) te-IN Telugu - (India) tg-TJ Tajik - (Tajikistan) th-TH Thai - (Thailand) tk-TM Turkmen - (Turkmenistan) tl-PH Tagalog - (Philippines) tr-TR Turkish - (Turkey) uk-UA Ukrainian - (Ukraine) ur-PK Urdu - (Pakistan) uz-UZ Uzbek - (Uzbekistan) vi-VN Vietnamese - (Viet Nam) zh-CN Chinese - (China) zh-HK Chinese - (Hong Kong) zh-TW Chinese - (Taiwan) */ $WClanguages = array( // our template language codes v.s. lang:LL codes for JSON // 'af' => 'AF', 'bg' => 'bg-BG', 'cs' => 'cs-CZ', 'ct' => 'ca-ES', 'dk' => 'da-DK', 'nl' => 'nl-NL', 'en' => 'en-US', 'fi' => 'fi-FI', 'fr' => 'fr-FR', 'de' => 'de-DE', 'el' => 'el-GR', // 'ga' => 'IR', 'it' => 'it-IT', 'he' => 'he-IL', 'hu' => 'hu-HU', 'no' => 'no-NO', 'pl' => 'pl-PL', 'pt' => 'pt-PT', 'ro' => 'ro-RO', 'es' => 'es-ES', 'se' => 'sv-SE', 'si' => 'sl-SI', 'sk' => 'sk-SK', 'sr' => 'sr-RS', ); $WClangCharsets = array( 'bg' => 'ISO-8859-5', 'el' => 'ISO-8859-7', 'he' => 'UTF-8', 'hu' => 'ISO-8859-2', 'ro' => 'ISO-8859-2', 'pl' => 'ISO-8859-2', 'si' => 'ISO-8859-2', 'ru' => 'ISO-8859-5' ); } // end loadLangDefaults // ------------------------------------------------------------------ // decode UV to word+color for display function WC_get_UVrange ( $inUV, $inUVwords ) { // figure out a text value and color for UV exposure text // 0 to 2 Low // 3 to 5 Moderate // 6 to 7 High // 8 to 10 Very High // 11+ Extreme if(strpos($inUV,',') !== false ) { $uv = preg_replace('|,|','.',$inUV); } else { $uv = $inUV; } switch (TRUE) { case ($uv == 0): $uv = ''; break; case (($uv > 0) and ($uv < 3)): $uv = ' ' . $inUVwords . ' '; break; case (($uv >= 3) and ($uv < 6)): $uv = ' ' . $inUVwords . ' '; break; case (($uv >=6 ) and ($uv < 8)): $uv = ' ' . $inUVwords . ' '; break; case (($uv >=8 ) and ($uv < 11)): $uv = ' ' . $inUVwords . ' '; break; case (($uv >= 11) ): $uv = ' ' . $inUVwords . ' '; break; } // end switch return $uv; } // end WC_get_UVrange // ------------------------------------------------------------------ // print one row of WC data in table (V1.03+) function WC_printRow($WCvar,$indexList,$style="") { global $wdth,$doRTL,$doDebug; if(!$doRTL) { print " \n"; } else { print " \n"; } foreach ($indexList as $k => $idx) { $cm = $doDebug?"":''; if(isset($WCvar[$idx])) { print " $WCvar[$idx]$cm\n"; } else { print " $cm\n"; } } print " \n"; } // end WC_printRow // End of functions -------------------------------------------------------------------------- ?>