X-Git-Url: http://gb7djk.dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=yr.php;fp=yr.php;h=22bb30d2a34ff6cebab58c167a2703f609717a13;hb=4f77e5fc357ae3bce202fe32fe4a5333aa1ee446;hp=0000000000000000000000000000000000000000;hpb=631bc0f2b224c9ebfd1dd5827814e5aba3e6d023;p=dweather.git
diff --git a/yr.php b/yr.php
new file mode 100644
index 0000000..22bb30d
--- /dev/null
+++ b/yr.php
@@ -0,0 +1,763 @@
+
+
+ ###### Changelog
+
+ Versjon: 2.6 - Lennart André Rolland (lennart.andre.rolland@nrk.no) / NRK - 2008.11.11 11:48
+ * Added option to remove banner ($yr_use_banner)
+ * Added option to allow any target for yr.no urls ($yr_link_target)
+
+ Versjon: 2.5 - Lennart André Rolland (lennart.andre.rolland@nrk.no) / NRK - 2008.09.25 09:24
+ * Cache will now update on parameter changes (cache file is prefixed with md5 digest of all relevant parameters)
+ This change will in the future make it easier to use the script for multiple locations in one go.
+ * Most relevant comments translated to english
+
+ Versjon 2.4 - Sven-Ove Bjerkan (sven-ove@smart-media.no) / Smart-Media AS - 2008.10.22 12:14
+ * Endret funksjonalitet ifbm med visning av PHP-feil (fjernet blant annet alle "@", dette styres av error_reporting())
+ * Ved feilmelding så ble denne lagret i lokal cache slik at man fikk opp feilmld hver gang inntil "$yr_maxage" inntreffer og den forsøker å laste på nytt - den cacher nå ikke hvis det oppstår en feil
+ * $yr_use_text, $yr_use_links og $yr_use_table ble overstyrt til "true" uavhengig av brukerens innstilling - rettet!
+
+ Versjon: 2.3 - Lennart André Rolland (lennart.andre.rolland@nrk.no) / NRK - 2008.09.25 09:24
+ * File permissions updated
+ * Caching is stored in HTML isntead of XML for security
+ * Other security and efficiency improvements
+
+
+
+ ###### INSTRUCTIONS:
+
+ 1. Only edit this script in editors with ISO-8859-1 or ISO-8859-15 character set.
+ 2. Edit the settings below
+ 3. Transfer the script to a folder in your webroot.
+ 4. Make sure that the webserver has write access to the folder where thsi script is placed. It will create a folder called yr-cache and place cached HTML data in that directory.
+
+ */
+
+/// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /
+/// /// /// /// /// Settings /// /// /// /// /// /// /// /// //
+// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
+
+// 1. Lenke: Lenke til stedet på yr.no (Uten siste skråstrek. Bruk vanlig æøå i lenka )
+// Link: Link to the url for the location on yr.no (Without the last Slash.)
+$yr_url='http://www.yr.no/sted/Norge/Vest-Agder/Lyngdal/Kvås';
+$yr_url='http://www.yr.no/stad/Sverige/Jämtland/Lofsdalen';
+
+// 2. Stedsnavnet: Skriv inn navnet på stedet. La stå tom for å falle tilbake til navnet i lenken
+// Location: The name of the location. Leave empty to fallback to the location in the url.
+$yr_name='';
+
+// 3. Bruk header og footer: Velg om du vil ha med header og/eller footer
+// Use Header and footers: Select to have HTML headers/footers wrapping the content (useful for debugging)
+//PS: Header for HTML dokumentet er XHTML 1.0 Strict
+// Skrus som regel av når du inlemmer i eksisterende dokument!
+//
+$yr_use_header=$yr_use_footer=true;
+
+// 4. Deler: Velg delene av varselet du vil ta med!
+// Parts: Choose which parts of the forecast to include
+$yr_use_banner=true; //yr.no Banner
+$yr_use_text=false; //Tekstvarsel
+$yr_use_links=true; //Lenker til varsel på yr.no
+$yr_use_table=true; //Tabellen med varselet
+
+// 5. Mellomlagringstid: Antall sekunder før nytt varsel hentes fra yr.no.
+// Cachetime: Number of seconds to keep forecast in local cache
+// Den anbefalt verdien på 1200 vil oppdatere siden hver 20. minutt.
+//
+// PS: Vi ønsker at du setter 20 minutters mellomlagringstid fordi
+// det vil gi høyere ytelse, både for yr.no og deg! MEN for å få til dette
+// vil vi opprette en mappe og lagre en fil i denne mappen. Vi har gått
+// gjennom scriptet veldig nøye for å forsikre oss om at det er feilfritt.
+// Likevel er dette ikke helt uproblematisk i forhold til sikkerhet.
+// Hvis du har problemer med dette kan du sette $yr_maxage til 0 for å skru
+// av mellomlagringen helt!
+$yr_maxage=1200;
+
+// 6. Utløpstid: Denne instillingen lar deg velge hvor lenge yr.no har på å
+// levere varselet i sekunder.
+// Timeout: How long before this script gives up fetching data from yr.no
+//
+// Hvis yr.no skulle være nede eller det er
+// forstyrrelser i båndbredden ellers, vil varselet erstattes med en
+// feilmelding til situasjonen er bedret igjen. PS: gjelder kun når nytt
+// varsel hentes! Påvirker ikke varsel mens siden viser varsel fra
+// mellomlageret. Den anbefalte verdien på 10 sekunder fungerer bra.
+$yr_timeout=10;
+
+// 7. Mellomlagrinsmappe: Velg navn på mappen til mellomlagret data.
+// Cachefolder: Where to put cache data
+//
+//Dette scriptet vil forsøke å opprette mappen om den ikke finnes.
+$yr_datadir='yr_cache';
+
+
+// 8. Lenke mål: Velg hvilken target som skal brukes på lenker til yr.no
+// Link target: Choose which target to use for links to yr.no
+$yr_link_target='_top';
+
+// 9. Vis feilmeldinger: Sett til "true" hvis du vil ha feilmeldinger.
+// Show errors: Useful while debugging.
+//
+//greit ved feilsøking, men bør ikke være aktivert i drift.
+$yr_vis_php_feilmeldinger=true;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /
+/// /// /// /// /// Code /// /// /// /// /// /// /// /// /// //
+// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
+// Skru på feilmeldinger i starten
+if($yr_vis_php_feilmeldinger) {
+ error_reporting(E_ALL);
+ ini_set('display_errors', true);
+}
+else {
+ error_reporting(0);
+ ini_set('display_errors', false);
+}
+
+//Opprett en komunikasjon med yr
+$yr_xmlparse = &new YRComms();
+//Opprett en presentasjon
+$yr_xmldisplay = &new YRDisplay();
+
+$yr_try_curl=true;
+
+//Gjenomfør oppdraget basta bom.
+die($yr_xmldisplay->generateHTMLCached($yr_url, $yr_name, $yr_xmlparse, $yr_url, $yr_try_curl, $yr_use_header, $yr_use_footer, $yr_use_banner, $yr_use_text, $yr_use_links, $yr_use_table, $yr_maxage, $yr_timeout, $yr_link_target));
+
+
+/// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /
+/// /// /// /// /// Hjelpekode starter her /// /// /// /// /// //
+// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
+
+
+function retar($array, $html = false, $level = 0) {
+ if(is_array($array)){
+ $space = $html ? " " : " ";
+ $newline = $html ? " Værvarsel fra yr.no, levert av Meteorologisk institutt og NRK.
" : "\n";
+ $spaces='';
+ for ($i = 1; $i <= 3; $i++)$spaces .= $space;
+ $tabs=$spaces;
+ for ($i = 1; $i <= $level; $i++)$tabs .= $spaces;
+ $output = "Array(" . $newline . $newline;
+ $cnt=sizeof($array);
+ $j=0;
+ foreach($array as $key => $value) {
+ $j++;
+ if (is_array($value)) {
+ $level++;
+ $value = retar($value, $html, $level);
+ $level--;
+ }
+ else $value="'$value'";
+ $output .= "$tabs'$key'=> $value";
+ if($j<$cnt)$output .= ',';
+ $output .= $newline;
+ }
+ $output.=$tabs.')'.$newline;
+ }
+ else{
+ $output="'$array'";
+ }
+ return $output;
+}
+
+
+// Klasse for lesing og tilrettelegging av YR data
+class YRComms{
+
+ //Generer gyldig yr.no array med værdata byttet ut med en enkel feilmelding
+ private function getYrDataErrorMessage($msg="Feil"){
+ return Array(
+ '0'=> Array('tag'=> 'WEATHERDATA','type'=> 'open','level'=> '1'),
+ '1'=> Array('tag'=> 'LOCATION','type'=> 'open','level'=> '2'),
+ '2'=> Array('tag'=> 'NAME','type'=> 'complete','level'=> '3','value'=> $msg),
+ '3'=> Array('tag'=> 'LOCATION','type'=> 'complete','level'=> '3'),
+ '4'=> Array( 'tag'=> 'LOCATION', 'type'=> 'close', 'level'=> '2'),
+ '5'=> Array( 'tag'=> 'FORECAST', 'type'=> 'open', 'level'=> '2'),
+ '6'=> Array( 'tag'=> 'ERROR', 'type'=> 'complete', 'level'=> '3', 'value'=> $msg),
+ '7'=> Array( 'tag'=> 'FORECAST', 'type'=> 'close', 'level'=> '2'),
+ '8'=> Array( 'tag'=> 'WEATHERDATA', 'type'=> 'close', 'level'=> '1')
+ );
+ }
+
+ //Generer gyldig yr.no XML med værdata byttet ut med en enkel feilmelding
+ private function getYrXMLErrorMessage($msg="Feil"){
+ $msg=$this->getXMLEntities($msg);
+ //die('errmsg:'.$msg);
+ $data=<<LO:'.retar($data));
+ }
+ //die('
XML for:'.$xml_url.' WAS: '.$data);
+ // Når vi har kommet hit er det noe som tyder på at vi har lykkes med å laste værdata, ller i det minste lage en teilmelding som beskriver eventuelle problemer
+ return $data;
+ }
+
+ // Last XML til en array struktur
+ private function parseXMLIntoStruct($data){
+ global $yr_datadir;
+ $parser = xml_parser_create('ISO-8859-1');
+ if((0==$parser)||(FALSE==$parser))return $this->getYrDataErrorMessage('Det oppstod en feil mens værdata ble forsøkt hentet fra yr.no. Teknisk info: Kunne ikke lage XML parseren.');
+ $vals = array();
+ //die('
'.retar($data).'
');
+ if(FALSE==xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1))return $this->getYrDataErrorMessage('Det oppstod en feil mens værdata ble forsøkt hentet fra yr.no. Teknisk info: Kunne ikke stille inn XML-parseren.');
+ if(0==xml_parse_into_struct($parser, $data, $vals, $index))return $this->getYrDataErrorMessage('Det oppstod en feil mens værdata ble forsøkt hentet fra yr.no. Teknisk info: Parsing av XML feilet.');
+ if(FALSE==xml_parser_free($parser))return $this->getYrDataErrorMessage('Det oppstod en feil mens værdata ble forsøkt hentet fra yr.no. Kunne ikke frigjøre XML-parseren.');
+ //die(''.retar($vals).'
');
+ return $vals;
+ }
+
+
+ // Rense tekst data (av sikkerhetshensyn)
+ private function sanitizeString($in){
+ //return $in;
+ if(is_array($in))return $in;
+ if(null==$in)return null;
+ return htmlentities(strip_tags($in));
+ }
+
+ // Rense tekst data (av sikkerhetshensyn)
+ public function reviveSafeTags($in){
+ //$in=$in.'STRONG UNDERLINE BOLD ITALICS';
+ return str_ireplace(array('<strong>','</strong>','<u>','</u>','<b>','</b>','<i>','</i>'),array('','','','','','','',''),$in);
+ }
+
+
+
+ private function rearrangeChildren($vals, &$i) {
+ $children = array(); // Contains node data
+ // Sikkerhet: sørg for at all data som parses strippes for farlige ting
+ if (isset($vals[$i]['value']))$children['VALUE'] = $this->sanitizeString($vals[$i]['value']);
+ while (++$i < count($vals)){
+ // Sikkerhet: sørg for at all data som parses strippes for farlige ting
+ if(isset($vals[$i]['value']))$val=$this->sanitizeString($vals[$i]['value']);
+ else unset($val);
+ if(isset($vals[$i]['type']))$typ=$this->sanitizeString($vals[$i]['type']);
+ else unset($typ);
+ if(isset($vals[$i]['attributes']))$atr=$this->sanitizeString($vals[$i]['attributes']);
+ else unset($atr);
+ if(isset($vals[$i]['tag']))$tag=$this->sanitizeString($vals[$i]['tag']);
+ else unset($tag);
+ // Fyll inn strukturen vær slik vi vil ha den
+ switch ($vals[$i]['type']){
+ case 'cdata': $children['VALUE']=(isset($children['VALUE']))?$val:$children['VALUE'].$val; break;
+ case 'complete':
+ if (isset($atr)) {
+ $children[$tag][]['ATTRIBUTES'] = $atr;
+ $index = count($children[$tag])-1;
+ if (isset($val))$children[$tag][$index]['VALUE'] = $val;
+ else $children[$tag][$index]['VALUE'] = '';
+ } else {
+ if (isset($val))$children[$tag][]['VALUE'] = $val;
+ else $children[$tag][]['VALUE'] = '';
+ }
+ break;
+ case 'open':
+ if (isset($atr)) {
+ $children[$tag][]['ATTRIBUTES'] = $atr;
+ $index = count($children[$tag])-1;
+ $children[$tag][$index] = array_merge($children[$tag][$index],$this->rearrangeChildren($vals, $i));
+ } else $children[$tag][] = $this->rearrangeChildren($vals, $i);
+ break;
+ case 'close': return $children;
+ }
+ }
+ }
+ // Ommøbler data til å passe vårt formål, og returner
+ private function rearrangeDataStruct($vals){
+ //die(''.$this->retar($vals).'<\pre>');
+ $tree = array();
+ $i = 0;
+ if (isset($vals[$i]['attributes'])) {
+ $tree[$vals[$i]['tag']][]['ATTRIBUTES']=$vals[$i]['attributes'];
+ $index=count($tree[$vals[$i]['tag']])-1;
+ $tree[$vals[$i]['tag']][$index]=array_merge($tree[$vals[$i]['tag']][$index], $this->rearrangeChildren($vals, $i));
+ } else $tree[$vals[$i]['tag']][] = $this->rearrangeChildren($vals, $i);
+ //die("
".retar($tree));
+ //Hent ut det vi bryr oss om
+ if(isset($tree['WEATHERDATA'][0]['FORECAST'][0]))return $tree['WEATHERDATA'][0]['FORECAST'][0];
+ else return YrComms::getYrDataErrorMessage('Det oppstod en feil ved behandling av data fra yr.no. Vennligst gjør administrator oppmerksom på dette! Teknisk: data har feil format.');
+ }
+
+ // Hovedmetode. Laster XML fra en yr.no URI og parser denne
+ public function getXMLTree($xml_url, $try_curl, $timeout){
+ // Last inn XML fil og parse til et array hierarcki, ommøbler data til å passe vårt formål, og returner
+ return $this->rearrangeDataStruct($this->parseXMLIntoStruct($this->loadXMLData($xml_url,$try_curl,$timeout)));
+ }
+
+ // Statisk hjelper for å parse ut tid i yr format
+ public function parseTime($yr_time, $do24_00=false){
+ $yr_time=str_replace(":00:00", "", $yr_time);
+ if($do24_00)$yr_time=str_replace("00", "24", $yr_time);
+ return $yr_time;
+ }
+
+ // Statisk hjelper for å besørge riktig encoding ved å oversette spesielle ISO-8859-1 karakterer til HTML/XHTML entiteter
+ public function convertEncodingEntities($yrraw){
+ $conv=str_replace("æ", "æ", $yrraw);
+ $conv=str_replace("ø", "ø", $conv);
+ $conv=str_replace("å", "å", $conv);
+ $conv=str_replace("Æ", "Æ", $conv);
+ $conv=str_replace("Ø", "Ø", $conv);
+ $conv=str_replace("Å", "Å", $conv);
+ return $conv;
+ }
+
+ // Statisk hjelper for å besørge riktig encoding vedå oversette spesielle UTF karakterer til ISO-8859-1
+ public function convertEncodingUTF($yrraw){
+ $conv=str_replace("æ", "æ", $yrraw);
+ $conv=str_replace("ø", "ø", $conv);
+ $conv=str_replace("Ã¥", "å", $conv);
+ $conv=str_replace("Ã", "Æ", $conv);
+ $conv=str_replace("Ã", "Ø", $conv);
+ $conv=str_replace("Ã
", "Å", $conv);
+ return $conv;
+ }
+
+
+ public function getXMLEntities($string){
+ return preg_replace('/[^\x09\x0A\x0D\x20-\x7F]/e', '$this->_privateXMLEntities("$0")', $string);
+ }
+
+ private function _privateXMLEntities($num){
+ $chars = array(
+ 128 => '€', 130 => '‚',
+ 131 => 'ƒ', 132 => '„',
+ 133 => '…', 134 => '†',
+ 135 => '‡',136 => 'ˆ',
+ 137 => '‰',138 => 'Š',
+ 139 => '‹',140 => 'Œ',
+ 142 => 'Ž', 145 => '‘',
+ 146 => '’',147 => '“',
+ 148 => '”',149 => '•',
+ 150 => '–',151 => '—',
+ 152 => '˜',153 => '™',
+ 154 => 'š',155 => '›',
+ 156 => 'œ',158 => 'ž',
+ 159 => 'Ÿ');
+ $num = ord($num);
+ return (($num > 127 && $num < 160) ? $chars[$num] : "".$num.";" );
+ }
+}
+
+// Klasse for å vise data fra yr. Kompatibel med YRComms sin datastruktur
+class YRDisplay{
+
+ // Akkumulator variabl for å holde på generert HTML
+ var $ht='';
+ // Yr Url
+ var $yr_url='';
+ // Yr stedsnavn
+ var $yr_name='';
+ // Yr data
+ var $yr_data=Array();
+
+ //Filename for cached HTML. MD5 hash will be prepended to allow caching of several pages
+ var $datafile='yr.html';
+ //The complete path to the cache file
+ var $datapath='';
+
+ // Norsk grovinndeling av de 360 grader vindretning
+ var $yr_vindrettninger=array(
+ 'nord','nord-nordøst','nordøst','øst-nordøst',
+ 'øst','øst-sørøst','sørøst','sør-sørøst',
+ 'sør','sør-sørvest', 'sørvest','vest-sørvest',
+ 'vest', 'vest-nordvest','nordvest', 'nord-nordvest', 'nord');
+
+ // Hvor hentes bilder til symboler fra?
+ var $yr_imgpath='http://fil.nrk.no/yr/grafikk/sym/b38';
+
+
+ //Generer header for varselet
+ public function getHeader($use_full_html){
+ // Her kan du endre header til hva du vil. NB! Husk å skru det på, ved å endre instillingene i toppen av dokumentet
+ if($use_full_html){
+ $this->ht.=<<
+
+EOT
+ ;
+ }
+
+
+ //Generer Copyright for data fra yr.no
+ public function getCopyright($target='_top'){
+ $url=YRComms::convertEncodingEntities($this->yr_url);
+ /*
+ Du må ta med teksten nedenfor og ha med lenke til yr.no.
+ Om du fjerner denne teksten og lenkene, bryter du vilkårene for bruk av data fra yr.no.
+ Det er straffbart å bruke data fra yr.no i strid med vilkårene.
+ Du finner vilkårene på http://www.yr.no/verdata/1.3316805
+ */
+ $this->ht.=<<
Værsymbolet og nedbørsvarselet gjelder for hele perioden, temperatur- og vindvarselet er for det første tidspunktet. <1 mm betyr at det vil komme mellom 0,1 og 0,9 mm nedbør.
+ Slik forstår du varslene fra yr.no.
Vil du også ha værvarsel fra yr.no på dine nettsider?
+EOT + ; + } + + + // Handle cache directory (re)creation and cachefile name selection + private function handleDataDir($clean_datadir=false,$summary=''){ + global $yr_datadir; + // The md5 sum is to avoid caching to the same file on parameter changes + $this->datapath=$yr_datadir .'/'. ($summary!='' ? (md5($summary).'['.$summary.']_') : '').$this->datafile; + // Delete cache dir + if ($clean_datadir) { + unlink($this->datapath); + rmdir($yr_datadir); + } + // Create new cache folder with correct permissions + if(!is_dir($yr_datadir))mkdir($yr_datadir,0300); + } + + + //Main with caching + public function generateHTMLCached($url,$name,$xml, $url, $try_curl, $useHtmlHeader=true, $useHtmlFooter=true, $useBanner=true, $useText=true, $useLinks=true, $useTable=true, $maxage=0, $timeout=10, $urlTarget='_top'){ + //Default to the name in the url + if(null==$name||''==trim($name))$name=array_pop(explode('/',$url)); + $this->handleDataDir(false,htmlentities("$name.$useHtmlHeader.$useHtmlFooter.$useBanner.$useText.$useLinks.$useTable.$maxage.$timeout.$urlTarget")); + $yr_cached = $this->datapath; + // Clean name + $name=YRComms::convertEncodingUTF($name); + $name=YRComms::convertEncodingEntities($name); + // Clean URL + $url=YRComms::convertEncodingUTF($url); + // Er mellomlagring enablet, og trenger vi egentlig laste ny data, eller holder mellomlagret data? + if(($maxage>0)&&((file_exists($yr_cached))&&((time()-filemtime($yr_cached))<$maxage))){ + $data['value']=file_get_contents($yr_cached); + // Sjekk for feil + if(false==$data['value']){ + $data['value']='Det oppstod en feil mens værdata ble lest fra lokalt mellomlager. Vennligst gjør administrator oppmerksom på dette! Teknisk: Sjekk at rettighetene er i orden som beskrevet i bruksanvisningen for dette scriptet
'; + $data['error'] = true; + } + } + // Vi kjører live, og saver samtidig en versjon til mellomlager + else{ + $data=$this->generateHTML($url,$name,$xml->getXMLTree($url, $try_curl, $timeout),$useHtmlHeader,$useHtmlFooter,$useBanner,$useText,$useLinks,$useTable,$urlTarget); + // Lagre til mellomlager + if($maxage>0 && !$data['error'] ){ + $f=fopen($yr_cached,"w"); + if(null!=$f){ + fwrite($f,$data['value']); + fclose($f); + } + } + } + // Returner resultat + return $data['value']; + } + + private function getErrorMessage(){ + if(isset($this->yr_data['ERROR'])){ + $error=$this->yr_data['ERROR'][0]['VALUE']; + //die(retar($error)); + $this->ht.='' .$error.'
'; + return true; + } + return false; + } + + //Main + public function generateHTML($url,$name,$data,$useHtmlHeader=true,$useHtmlFooter=true,$useBanner=true,$useText=true,$useLinks=true,$useTable=true,$urlTarget='_top'){ + // Fyll inn data fra parametrene + $this->ht=''; + $this->yr_url=$url; + $this->yr_name=$name; + $this->yr_data=$data; + + // Generer HTML i $ht + $this->getHeader($useHtmlHeader); + $data['error'] = $this->getErrorMessage(); + if($useBanner)$this->getBanner($urlTarget); + $this->getCopyright($urlTarget); + if($useText)$this->getWeatherText(); + if($useLinks)$this->getLinks($urlTarget); + if($useTable){ + $this->getWeatherTableHeader(); + $this->getWeatherTableContent(); + $this->getWeatherTableFooter($urlTarget); + } + $this->getFooter($useHtmlFooter); + + // Returner resultat + //return YRComms::convertEncodingEntities($this->ht); + $data['value'] = $this->ht; + return $data; + } +} + +?> \ No newline at end of file