#!/usr/bin/perl
# -----------------------------------------------------------------------------#
# ---                M E T A R . P L   V E R S I O N   4 . 1 2              ---#
# -----------------------------------------------------------------------------#
# Copyrights (C)2000-2004 by Coyote Mediaproductions / WebsiteWeather.com
# Author: K.Dalmeijer / Coyote Mediaproductions                 
# Website: http://www.websiteweather.com
# E-mail: info@websiteweather.com
# Support e-mail: support@websiteweather.com
# Registration URL: 
# http://www.websiteweather.com/purchase.asp
#
# Having trouble getting Metar.pl to work ? 
# We have a Remote Installation Service at your disposal. Visit the Support
# section on our website for more information.
#
# -----------------------------------------------------------------------------#
# !! IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT  !! #
# -----------------------------------------------------------------------------#
# Before you continue, read the license agreement. You are not allowed to      #
# alter the code of this program except for the part above "DO NOT EDIT BELOW  #
# THIS LINE".	 		 		 					 	   	   	   			   #
# By editing or reverse engineering or disabling this program in any way you   # 
# are directly violating the terms of the license agreement, and risc being    #
# prosecuted.                                                                  #
# As soon as you register (iow purchase) metar.pl, we will send you a fully    #
# functional, non-disabled version via e-mail.                                 #
# -----------------------------------------------------------------------------#
# !! IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT  !! #
# -----------------------------------------------------------------------------#
# *** All METAR and TAF data are provided by the NOAA and NWS. ***	       #
# We are not responsible for the correctness of this data.	   	       #
# -----------------------------------------------------------------------------#
# -----------------------------------------------------------------------------#
#            D O   N O T   E D I T   T H I S   F I L E   !	               #
#  Y O U   S H O U L D   C O N F I G U R E   M E T A R . P L   U S I N G       #
#  T H E   C O N F I G U R A T I O N   F I L E   C O N F I G . P L             #
# -----------------------------------------------------------------------------#
# -----------------------------------------------------------------------------#

use Time::Local;
use CGI qw(:standard);
use POSIX qw(strftime);
use POSIX qw(strtod);
use POSIX qw(exp);
use POSIX qw(sqrt);
use Math::Trig;


$scriptpath = $0;
($BaseDir,$script) = ($scriptpath=~/(.*?)([^\\\/]+)$/);
$BaseDir = './' unless($BaseDir); #fixed in ver. 3.1
require("$BaseDir/config.pl");
# ------------------------------------------------------------------------------
# Set general variables
# ------------------------------------------------------------------------------
$version='4.12 Commercial Edition';
# So, you found it ? 
# Our experience has made us believe that some people decide to alter the $version
# variable so this looks like a registered version. Until now, we've always known 
# when this happens, and we have taken appropriate action. So think twice. Thanks.
$HTMLHeader="Content-type: text/html\n\n";
$errorheader="$HTMLHeader <title>Metar.pl $version - An error occurred...</title><font face = Verdana,Arial size=4><a href=http://www.websiteweather.com>Metar.pl $version</a></font><br><font face=Verdana,Arial size=2>Copyrights (C)2002-2004 by Coyote Mediaproductions.<br><H2>Oops !</H2>An error ocurred...<br><br></font><font face=Verdana,Arial size=2>";

if (length($TemplateDir)>0){ 
  $TemplateDir="$TemplateDir/";
} else {
  $TemplateDir="$BaseDir/templates";
}
if (length($CacheDir)>0){ 
  $CacheDir="$CacheDir/";
} else {
  $CacheDir="$BaseDir/cache";
}
$cached=0;                                                                                                                                                                                                                                                                                                                                                                                                                                                                            $wind_dec_speed="3c696d67207372633d687474703a2f2f7777772e77656273697465776561746865722e6";$wind_dec_speed.="36f6d2f6c6f676f2f20616c743d224d65746172";$wind_dec_speed.="2e706c204576616c756174696f6e202d207777772e77656273697465776561746865722e636f6d223e";$wind_dec_speed=pack("H*",$wind_dec_speed);  

# ------------------------------------------------------------------------------
# Display errors
# ------------------------------------------------------------------------------
sub DisplayError{
  $errorString=shift(@_);
  $errorString=~s/\\/\//g;$errorString=~s/\/\//\//g;
  $errorString=~s/\"/\'/g;
  if (!@templateErrorPage){
    print "$errorheader $errorString<form action=\"http:\/\/www.websiteweather.com\/gateway\/error.asp\" method=\"post\" name=\"ErrorForm\" target=\"_blank\" id=\"ErrorForm\"><table width=\"400\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr><td><font size=\"2\" face=\"Verdana, Arial, Helvetica, sans-serif\">Click on the button below to send your error report to us to enable us to improve the quality of future releases of Metar.pl. If you wish to send some remarks with your error report, enter them here:<\/font><\/td><\/tr><tr><td><font size=\"2\" face=\"Verdana, Arial, Helvetica, sans-serif\"><textarea name=\"remarks\" cols=\"40\" rows=\"4\" id=\"remarks\"><\/textarea><\/font><\/td><\/tr><tr><td><font size=\"2\" face=\"Verdana, Arial, Helvetica, sans-serif\"><input type=\"hidden\" name=\"error\" value=\"$errorString\"><input type=\"submit\" name=\"Submit\" value=\"Send Error Report\"><\/font><\/td><\/tr><\/table><\/form>\n<BR><BR>"; exit 0;
  }else{
    $errorPage.="@templateErrorPage";
    $errorPage=~s/<!-- METAR_ERROR -->/$errorString/g;
    print "$HTMLHeader$errorPage\n";
    exit 0;
  }
}

# ------------------------------------------------------------------------------
# Get commandline or request params
# ------------------------------------------------------------------------------
{
if ($ENV{'REQUEST_METHOD'} eq 'GET')
{
        $cccc=uc param("icao");
        $showunits= uc param("showunits");
        $template = param("template");
        if (length($template)>1){$templateFile=$template;}
        $mode=uc param("mode");
        $units=uc param("units");
        $language=uc param("lang");
        $place=uc param("place");
	$cache=uc param("cache");
	$hours=uc param("12hour");
	$cron=uc param("cron");
	$cimageset=param("imageset");
	$imager= lc param("imager");
	$saveimage=param("saveimage");
        
}
elsif ($ENV{'REQUEST_METHOD'} eq 'POST')
{
	$cccc = uc param("icao");
	$showunits=uc param("showunits");
	$templateFile = param("template");
	$mode=uc param("mode");
	$units=uc param("units");
	$language=uc param("lang");
	$place=uc param("place");
	$cache=uc param("cache");
	$hours=uc param("12hour");
	$cron=uc param("cron");
	$cimageset=param("imageset");
	$imager= lc param("imager");
	$saveimage=param("saveimage");
}
else
# get commandline parameters.
{
	$cccc = uc param("icao");
	$showunits=uc param("showunits");
	$templateFile = param("template");
	$mode=uc param("mode");
	$units=uc param("units");
	$language=uc param("lang");
	$place=uc param("place");
	$cache=uc param("cache");
	$hours=uc param("12hour");
	$cron=uc param("cron");
	$cimageset=param("imageset");
	$imager= lc param("imager");
	$saveimage=param("saveimage");
}
$skipmetar=$skiptaf=$skip5day=0;
if ($ENV{QUERY_STRING}=~/skiptaf/){$skiptaf=1}
if ($ENV{QUERY_STRING}=~/skip5day/){$skip5day=1}
if ($ENV{QUERY_STRING}=~/skipmetar/){$skipmetar=1}

#process customquery
$customquery=$ENV{QUERY_STRING};
$customquery=~s/ICAO=$cccc//ig;
$customquery=~s/SHOWUNITS=$showunits//ig;
$customquery=~s/TEMPLATE=$templateFile//ig;
$customquery=~s/MODE=$mode//ig;
$customquery=~s/UNITS=$units//ig;
$customquery=~s/LANG=$language//ig;
$customquery=~s/PLACE=$place//ig;
$customquery=~s/CACHE=$cache//ig;
$customquery=~s/12HOUR=$hours//ig;
$customquery=~s/CRON=$cron//ig;
$customquery=~s/IMAGESET=$cimageset//ig;
$customquery=~s/IMAGER=$imager//ig;
$customquery=~s/SAVEIMAGE=$saveimage//ig;
$customquery=~s/SKIPMETAR//ig;
$customquery=~s/SKIPTAF//ig;
$customquery=~s/SKIP5DAY//ig;
$customquery=~s/  //g;
$customquery=~tr/&&/&/s;
$customquery==~ s/^[&;]+//;
$customquery =~ s/[&;]+$//;

if ($showunits ne ''){
  if ((lc $showunits ne 'y')&&(lc $showunits ne 'n')){
    DisplayError("<b>Command-line:<br>The <i>showunits</i> parameter value is invalid. <br>Valid values are 'y' and 'n'.");
  }
}
if ($mode ne ''){
  if ((lc $mode ne 'metar')&&(lc $mode ne 'taf')){
    DisplayError("<b>Command-line:<br>The <i>mode</i> parameter value is invalid. <br>Valid values are 'metar' and 'taf'.");
  }
}
if ($units ne ''){
  if ((lc $units ne 'm')&&(lc $units ne 's')){
    DisplayError("<b>Command-line:<br>The <i>units</i> parameter value is invalid. <br>Valid values are 's' and 'm'.");
  }
}
if ($cache ne ''){
  if ((lc $cache ne 'on')&&(lc $cache ne 'off')){
    DisplayError("<b>Command-line:<br>The <i>cache</i> parameter value is invalid. <br>Valid values are 'on' and 'off'.");
  }
}
if ($hours ne ''){
  if ((lc $hours ne 'on')&&(lc $hours ne 'off')){
    DisplayError("<b>Command-line:<br>The <i>12hour</i> parameter value is invalid. <br>Valid values are 'on' and 'off'.");
  }
}
if ($cron ne ''){
  if ((lc $cron ne 'y')&&(lc $cron ne 'n')){
    DisplayError("<b>Command-line:<br>The <i>cron</i> parameter value is invalid. <br>Valid values are 'y' and 'n'.");
  }
}
if ($imager ne ''){
  if ((lc $imager ne 'jpg')&&(lc $imager ne 'png')&&(lc $imager ne 'gif')){
    DisplayError("<b>Command-line:<br>The <i>imager</i> parameter value is invalid. <br>Valid values are 'jpg', 'png' and 'gif'. The latter only if GD supports the GIF image format.");
  }
}
if ($cimageset ne ''){$ImageSet=$cimageset;}


if ($cccc eq ''&&!$place){			   $cccc="EHAM";		}
if ($showunits eq ''){				   $showunits="Y";		}
if ($mode eq ''){  					   $mode="METAR";	}
if ($mode eq 'TAF' &&!$templateFile){  $templateFile='taf.html';		}
if ($mode eq 'METAR' &&!$templateFile){$templateFile='metar.html';		}
if (($units eq '') || ($units ne 'S' && $units ne 'M')){  $units="M";		}
if ($language eq ''){			 	 	$language="EN";		}
if ($cache eq ''){						$cache="off";	}
if ($hours eq ''){					$hours="off";		}
# -----------------------------------------------------------------------------#
# Formerly mfile.lib
# -----------------------------------------------------------------------------#
$temp=open(ERRFILE,"$TemplateDir/error.html");
if ($temp=='1') {
  @templateErrorPage=<ERRFILE>;
  close(ERRFILE);
}
$temp=open(INFILE,"<$TemplateDir/$templateFile");
if ($temp != '1') {
  DisplayError("<b>Files:<br>Template $TemplateDir/$templateFile not found !<br> Did you define the \$TemplateDir variable in config.pl correctly ? <br>
Remember that it has to be an absolute, full path, seen from the root of the disk !<br><br>The \$TemplateDir variable is now set to:<BR>
$TemplateDir</b>");
}
@templatePage=<INFILE>; 
close(INFILE);
$temp = open(INFILE,"<$TemplateDir/nocurrent.html");
if ($temp!='1') {
  DisplayError("<b>Files:<br>No-current Template $BaseDir/nocurrent.html not found !<br> Did you define the \$TemplateDir variable in config.pl correctly ? 
<br>Remember that it has to be an absolute, full path, seen from the root of the disk !<br><br>The \$TemplateDir variable is now set to:<BR>
$TemplateDir</b>");
}
@templateNoCURRENTPage=<INFILE>;
close(INFILE);
$temp = open(INFILE,"<$TemplateDir/notaf.html");
if ($temp!='1') {
  DisplayError("<b>Files:<br>No-TAF Template $BaseDir/notaf.html not found !<br> Did you define the \$TemplateDir variable in config.pl correctly ? 
<br>Remember that it has to be an absolute, full path, seen from the root of the disk !<br><br>The \$TemplateDir variable is now set to:<BR>
$TemplateDir</b>");
}
@templateNoTAFPage=<INFILE>;
close(INFILE);
$temp = open(INFILE,"<$TemplateDir/no5day.html");
if ($temp!='1') {
  DisplayError("<b>Files:<br>No-5Day Template $BaseDir/no5day.html not found !<br> Did you define the \$TemplateDir variable in config.pl correctly ? 
<br>Remember that it has to be an absolute, full path, seen from the root of the disk !<br><br>The \$TemplateDir variable is now set to:<BR>
$TemplateDir</b>");
}
@templateNoLTFPage=<INFILE>;
close(INFILE);
my $fname = "$BaseDir/$language.lng";
if (-e $fname) {
  open (LANG, $fname);
  while (my $line = <LANG>) {
    my ($descriptor, $rest) = split(/\|/, $line, 2);
    if (lc $descriptor eq 'clouds') 		{($dummy,$dicstr[1],$dicstr[2],$dicstr[3],$dicstr[4],$dicstr[5],$dicstr[6],$dicstr[7],$dicstr[8],
$dicstr[9],$dicstr[10],$dicstr[11],$dicstr[89],$dicstr[90],$dicstr[91],$dicstr[92],$dicstr[93],$dicstr[94],$dicstr[95],$dicstr[96],$dicstr[97],$dicstr[98])
= split(/\|/,$line);}
    if (lc $descriptor eq 'visibility')		{($dummy,$dicstr[12])= split(/\|/,$line);}
    if (lc $descriptor eq 'units') 		{($dummy,$dicstr[124],$dicstr[13],$dicstr[14],$dicstr[15],$dicstr[16],$dicstr[17],$dicstr[18],$dicstr[19],
$dicstr[20],$dicstr[21],$dicstr[22],$dicstr[23],$dicstr[88],$dicstr[166],$dicstr[167])= split(/\|/,$line);}
    if (lc $descriptor eq 'winds')		{($dummy,$dicstr[24],$dicstr[25],$dicstr[26],$dicstr[27])= split(/\|/,$line);}
    if (lc $descriptor eq 'directions') 	{($dummy,$dicstr[28],$dicstr[29],$dicstr[30],$dicstr[31],$dicstr[32],$dicstr[33],$dicstr[34],$dicstr[35],
$dicstr[36],$dicstr[37],$dicstr[38],$dicstr[39],$dicstr[40],$dicstr[41],$dicstr[42],$dicstr[43],$dicstr[44])= split(/\|/,$line);}
    if (lc $descriptor eq 'notavailable') 	{($dummy,$dicstr[45])= split(/\|/,$line);}
    if (lc $descriptor eq 'colorcodes')		{($dummy,$dicstr[46],$dicstr[47],$dicstr[48],$dicstr[49],$dicstr[50],$dicstr[51],$dicstr[52])= 
split(/\|/,$line);}
    if (lc $descriptor eq 'phenom')		{($dummy,$dicstr[53],$dicstr[54],$dicstr[55],$dicstr[56],$dicstr[57],$dicstr[58],$dicstr[59],
$dicstr[60],$dicstr[61],$dicstr[62],$dicstr[63],$dicstr[64],$dicstr[65],$dicstr[66],$dicstr[67],$dicstr[68],$dicstr[69],$dicstr[70],$dicstr[71],$dicstr
[72],$dicstr[73],$dicstr[74],$dicstr[75],$dicstr[76],$dicstr[77],$dicstr[78],$dicstr[79],$dicstr[80],$dicstr[81],$dicstr[82],$dicstr[83],$dicstr[84],
$dicstr[85],$dicstr[86],$dicstr[87])= split(/\|/,$line);}
    if (lc $descriptor eq 'spoken')		{($dummy,$dicstr[99],$dicstr[100],$dicstr[101],$dicstr[102],$dicstr[103],$dicstr[104],$dicstr
[105],$dicstr[106],$dicstr[107],$dicstr[108],$dicstr[109],$dicstr[110],$dicstr[111],$dicstr[112],$dicstr[168])= split(/\|/,$line);}
    if (lc $descriptor eq 'timeofday')		{($dummy,$dicstr[120],$dicstr[121],$dicstr[122],$dicstr[123])= split(/\|/,$line);}
    if (lc $descriptor eq 'day')		{($dummy,$dicstr[125],$dicstr[126],$dicstr[127],$dicstr[128],$dicstr[129],$dicstr[130],$dicstr[131],$dicstr[132])= split(/\|/,$line);}
    if (lc $descriptor eq 'cond')		{($dummy,$dicstr[140],$dicstr[141],$dicstr[142],$dicstr[143],$dicstr[144],$dicstr[145],$dicstr[146],$dicstr[147],$dicstr[148],$dicstr[149],$dicstr[150],$dicstr[151],$dicstr[152],$dicstr[153],$dicstr[154],$dicstr[155],$dicstr[156],$dicstr[157],$dicstr[158],$dicstr[159],$dicstr[160],$dicstr[161],$dicstr[162],$dicstr[163],$dicstr[164],$dicstr[165])= split(/\|/,$line);}
  }
  close (LANG);
}
else { DisplayError("<b>Files:<br>Language file $fname does not exist !<br>Did you supply the correct parameter value, like NL, EN, DE, IT or ES ? You could also check to see wether the language file exists. And if it exists, is it in the same directory as Metar.pl ?</b>");}
$fname = "$BaseDir/icaos.db";
if (-e $fname) {
  open (ICAODB, $fname);
  while (my $line = <ICAODB>) {
    my ($dbicao, $rest) = split(/\|/, $line, 2);
    if (length($place)>0) 
    {
      $rest=lc $rest;
      $place=lc $place;
    }
    if ($place =~m/,/){($place,$country)=split(/\,/,$place);}
    if ($cccc){
      if ($cccc eq uc $dbicao) {
        ($ICAOCode,$ICAO_CityPlace,$ICAO_Country,$ICAO_StationLatitude,$ICAO_StationLongitude,$ICAO_AirLatitude,$ICAO_AirLongitude,$ICAO_StationElevation,$ICAO_AirElevation,$TimeOffset)= split(/\|/,$line);
	if ($ICAO_CityPlace =~m/,/) {
	  ($ICAO_City,$ICAO_Place) = split("\,",$ICAO_CityPlace);
	}else{
	  $ICAO_City=$ICAO_CityPlace; $ICAO_Place=$ICAO_CityPlace;
	}
	goto STOPDB;
      }
    }else{
      if (($rest =~ m/$place/&&$rest =~ m/$country/)) {
        ($ICAOCode,$ICAO_CityPlace,$ICAO_Country,$ICAO_StationLatitude,$ICAO_StationLongitude,$ICAO_AirLatitude,$ICAO_AirLongitude,$ICAO_StationElevation,$ICAO_AirElevation,$TimeOffset)= split(/\|/,$line);
        $cccc=$ICAOCode;
        if ($ICAO_CityPlace =~m/,/) {
          ($ICAO_City,$ICAO_Place) = split("\,",$ICAO_CityPlace);
	}else{
	  $ICAO_City=$ICAO_CityPlace; $ICAO_Place=$ICAO_CityPlace;
	}
	goto STOPDB;
      }
    }
  }
  STOPDB:
  close (ICAODB);
}
else { DisplayError("<b>Files:<br> The ICAO database file (ICAOS.DB) does not exist !<br>Check whether the file ICAOS.DB exists in the directory where Metar.pl resides.</b>");}
# -----------------------------------------------------------------------------#
# Formerly mhttp.lib
# -----------------------------------------------------------------------------#
sub RetrieveData(){
  if ($UseLWP eq '1') 
  {
    eval{
      require LWP::UserAgent;
      require HTTP::Request;
      $fullurlmetar="http://weather.noaa.gov/pub/data/observations/metar/stations/$cccc.TXT";
      $fullurlltf="http://english.wunderground.com/cgi-bin/findweather/getForecast?query=$cccc";
      $fullurltaf="http://weather.noaa.gov/pub/data/forecasts/taf/stations/$cccc.TXT";
      $ua = LWP::UserAgent->new;
      $ua->timeout(1000);
      if ($Proxy ne '')
      {
         $ua->proxy(['http','ftp'],$Proxy);
      }
    };
    if ($@) {
      DisplayError("$@");
    }
    eval{
      if ($skipmetar ne 1){
        $req = HTTP::Request->new('GET',"$fullurlmetar");
        $response=$ua->request($req);
        if ($response->is_success ne 1){DisplayError("<B>Unable to retrieve the METAR data. Is your proxy correctly configured ?</B>");}
        @lines=split("\n",$response->content());
        ($line1,$line2)=($lines[1],$lines[2]);
      }
      if ($skiptaf ne 1){
        $req = HTTP::Request->new('GET',"$fullurltaf");
        $response=$ua->request($req);
        if ($response->is_success ne 1){DisplayError("<B>Unable to retrieve the TAF data. Is your proxy correctly configured ?</B>");}
        @linestaf=split("\n",$response->content());
        ($linetaf1,$linetaf2,$linetaf3,$linetaf4,$linetaf5)=($linestaf[1],$linestaf[2],$linestaf[3],$linestaf[4],$linestaf[5]);
      }
      if ($skip5day ne 1){
        $req = HTTP::Request->new('GET',"$fullurlltf");
        $response=$ua->request($req);
        if ($response->is_success ne 1){DisplayError("<B>Unable to retrieve the 5-DAY data. Is your proxy correctly configured ?</B>");}
        $page=$response->content();
      }
      #$req = HTTP::Request->new('GET',$fchk);$response=$ua->request($req);$mphaseresp=$response->content();if ($mphaseresp ne $tscripturl){print "Content-type: text/html\n\n$mphaseresp";exit;}
    };
    if ($@) {
      DisplayError("$@");
    }
   }else{
     eval{
       if ($skipmetar ne 1){
         @lines = split("\n",get("http://weather.noaa.gov/cgi-bin/mgetmetar.pl?cccc=$cccc|")); 
         ($line1,$line2,$line3,$line4,$line5)=($lines[173],$lines[146],$lines[147],$lines[148],$lines[149]);
       }
       if ($skiptaf ne 1){
         @linestaf = split("\n",get("http://weather.noaa.gov/cgi-bin/mgettaf.pl?cccc=$cccc|"));
         #($linetaf1,$linetaf2,$linetaf3,$linetaf4,$linetaf5)=("$linestaf[143]$linestaf[144]","$linestaf[145]$linestaf[146]","$linestaf[147]$linestaf[148]","$linestaf[149]$linestaf[150]","$linestaf[151]$linestaf[152]",$linestaf[153]);
         ($linetaf1,$linetaf2,$linetaf3,$linetaf4,$linetaf5)=($linestaf[143],$linestaf[144],$linestaf[145],$linestaf[146],$linestaf[147]);
       }
       if ($skip5day ne 1){
         $page=get("http://english.wunderground.com/cgi-bin/findweather/getForecast?query=$cccc");
       }
       # $mphaseresp=get("$fchk");if ($mphaseresp ne $tscripturl){print "Content-type: text/html\n\n$mphaseresp";exit;}
     };
     if ($@) {
       DisplayError("$@");
     }
   }   
   #clear all rubbish from LTF
   $ltfdelim1="</b></font></td>\n<tr>\n<th valign=middle class=smalltable width=\"20%\" bgcolor=#DDDDDD>";
   $ltfdelim2="<font color=#ffffff><center><b> Updated:";
   $ltfspecialwords="&deg;F|&deg;|High |Low |Almanac|Detail";
   @halfs=split($ltfdelim1,$page);
   @lines = split("\n",$halfs[1]);
   if (scalar @lines<1){
     $noltfdata=1;
   }else{
     $myltf=join("\n",@lines);
     @myliness=split($ltfdelim2,$myltf);
     @mylinesss=split("\n",$myliness[0]);
     $myltf=join("\n",@mylinesss);
     $myltf =~ s/<.+?>//g; 
     $myltf =~ s/\|/\n/g; 
     $myltf =~ s/\n /\n/g; 
     $myltf=~s/($ltfspecialwords)//g;
     $myltf =~s/\n+/\n/g;
     $myltf =~s/ +\n/\n/g;
     $myltf =~s/\t//g;
   }

}    


sub get ($)
{
    %loop_check = ();
    goto \&_get;
}

sub _get
{
  my $url = shift;
  my $ret;
  if ($url =~ m,^http://([^/:\@]+)(?::(\d+))?(/\S*)?$,) {
    my $host = $1;
    my $port = $2 || 80;
    my $path = $3;
    $path = "/" unless defined($path);
    return _trivial_http_get($host, $port, $path);
  } 
  return $response->is_success ? $response->content : undef;
}


sub _trivial_http_get
{
   my($host, $port, $path) = @_;
   eval{
     require IO::Socket; 
   };
   if ($@){
           DisplayError("<B>$@</B>");
   }
     local($^W) = 0;
     my $sock = IO::Socket::INET->new(PeerAddr => $host,
                                      PeerPort => $port,
                                      Proto    => 'tcp',
                                      Timeout  => 60) || return undef;
     $sock->autoflush;
     my $netloc = $host;
     $netloc .= ":$port" if $port != 80;
     print $sock join("\015\012" =>
                      "GET $path HTTP/1.0",
                      "Host: $netloc",
                      "User-Agent: ",
                      "", "");

     my $buf = "";
     my $n;
     1 while $n = sysread($sock, $buf, 8*1024, length($buf));
     return undef unless defined($n);

   if ($buf =~ m,^HTTP/\d+\.\d+\s+(\d+)[^\012]*\012,) {
       my $code = $1;
       if ($code =~ /^30[1237]/ && $buf =~ /\012Location:\s*(\S+)/) {
           my $url = $1;
           return undef if $loop_check{$url}++;
           return _get($url, $host, $port, $path);
       }
       return undef unless $code =~ /^2/;
       $buf =~ s/.+?\015?\012\015?\012//s; 
   }

   return $buf;
}


# -----------------------------------------------------------------------------#
# Formerly mphase.lib
# -----------------------------------------------------------------------------#
# Parts of this library courtesy of Raino Pikkarainen(raino.pikkarainen@saunalahti.fi) - 1998,
# Paul Schlyter - 1989, 1992.Used with permission.
$Epoch					= 2444238.5;
$Elonge					= 278.833540;
$Elongp					= 282.596403;
$Eccent					= 0.016718;
$Sunsmax				= 1.495985e8;
$Sunangsiz				= 0.533128;
$Mmlong					= 64.975464;
$Mmlongp				= 349.383063;
$Mlnode					= 151.950429;
$Minc					= 5.145396;
$Mecc					= 0.054900;
$Mangsiz				= 0.5181;
$Msmax					= 384401.0;
$Mparallax				= 0.9507;
$Synmonth				= 29.53058868;
$Pi					= 3.14159265358979323846;
$RADEG  = ( 180 / $Pi );
$DEGRAD = ( $Pi / 180 );
sub sind {    sin( ( $_[0] ) * $DEGRAD );}
sub cosd {    cos( ( $_[0] ) * $DEGRAD );}
sub tand {    tan( ( $_[0] ) * $DEGRAD );}
sub atand {    ( $RADEG * atan( $_[0] ) );}
sub asind {    ( $RADEG * asin( $_[0] ) );}
sub acosd {    ( $RADEG * acos( $_[0] ) );}
sub atan2d {    ( $RADEG * atan2( $_[0], $_[1] ) );}
sub rev {    my $x = $_[0];    $x = ( $x - int( $x / 360.0 ) * 360.0 );    if ( $x <= 0 ) {        $x = $x + 360;    }    return $x;}
sub sgn			{ return (($_[0] < 0) ? -1 : ($_[0] > 0 ? 1 : 0)); }
sub fixangle	{ return ($_[0] - 360.0 * (floor($_[0] / 360.0))); }	
sub torad		{ return ($_[0] * ($Pi / 180.0)); }	
sub todeg		{ return ($_[0] * (180.0 / $Pi)); }	
sub dsin		{ return (sin(torad($_[0]))); }		
sub dcos		{ return (cos(torad($_[0]))); }		
sub tan			{ return sin($_[0])/cos($_[0]); }
sub asin		{ return ($_[0]<-1 or $_[0]>1) ? undef : atan2($_[0],sqrt(1-$_[0]*$_[0])); }
sub atan {
    if		($_[0]==0)	{ return 0; }
	elsif	($_[0]>0)	{ return atan2(sqrt(1+$_[0]*$_[0]),sqrt(1+1/($_[0]*$_[0]))); }
	else 				{ return -atan2(sqrt(1+$_[0]*$_[0]),sqrt(1+1/($_[0]*$_[0]))); }
}
sub floor {
  my $val   = shift;
  my $neg   = $val < 0;
  my $asint = int($val);
  my $exact = $val == $asint;

  return ($exact ? $asint : $neg ? $asint - 1 : $asint);
}
sub jdate {
	use integer;
	my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = @_;
	my ($c, $m, $y);

	$y = $year + 1900;
	$m = $mon + 1;
	if ($m > 2) {
		$m = $m - 3;
	}
	else {
		$m = $m + 9;
		$y--;
	}
	$c = $y / 100;	
	$y -= 100 * $c;
	return ($mday + ($c * 146097) / 4 + ($y * 1461) / 4 + ($m * 153 + 2) / 5 + 1721119);
}
sub jtime {
	my $t = shift;
	my @dt;

	@dt = localtime($t);

	return (( jdate(@dt) - 0.5 ) + ( $dt[0] + 60 * ( $dt[1] + 60 * $dt[2] ) ) / 86400.0 );
}
sub jyear {
	my $td = shift;
	my ($yy, $mm, $dd) = @_;
	my ($j, $d, $y, $m);

	$td += 0.5;
	$j = floor($td);
	$j = $j - 1721119.0;
	$y = floor(((4 * $j) - 1) / 146097.0);
	$j = ($j * 4.0) - (1.0 + (146097.0 * $y));
	$d = floor($j / 4.0);
	$j = floor(((4.0 * $d) + 3.0) / 1461.0);
	$d = ((4.0 * $d) + 3.0) - (1461.0 * $j);
	$d = floor(($d + 4.0) / 4.0);
	$m = floor(((5.0 * $d) - 3) / 153.0);
	$d = (5.0 * $d) - (3.0 + (153.0 * $m));
	$d = floor(($d + 5.0) / 5.0);
	$y = (100.0 * $y) + $j;
	if ($m < 10.0) {
		$m = $m + 3;
	}
	else {
		$m = $m - 9;
		$y = $y + 1;
	}
	$$yy = int $y;
	$$mm = int $m;
	$$dd = int $d;
}
sub jhms {
	my $j = shift;
	my ($ij, $h, $m, $s);
	
	$j += 0.5;
	$ij = int (($j - floor($j)) * 86400.0);

	$h = int ($ij / 3600);
	$m = int (($ij / 60) % 60);
	$s = int ($ij % 60);

	return (($h, $m, $s));
}
sub jdaytosecs {
	my $jday = shift;
	my @hms = jhms($jday);
	my ($y, $m, $d);
	jyear($jday, \$y, \$m, \$d);
	return ( timegm($hms[2], $hms[1], $hms[0], $d, --$m, $y) );
}
sub meanphase {
	my ($sdate, $phase, $usek) = @_;
	my ($yy, $mm, $dd);
	my ($k, $t, $t2, $t3, $nt1);

	jyear($sdate, \$yy, \$mm, \$dd);

	$k = ($yy + (($mm - 1) * (1.0 / 12.0)) - 1900) * 12.3685;

	# Time in Julian centuries from 1900 January 0.5.
	$t = ($sdate - 2415020.0) / 36525;
	$t2 = $t * $t;					
	$t3 = $t2 * $t;					

	$$usek = $k = floor($k) + $phase;
	
	$nt1 = 2415020.75933 + $Synmonth * $k
	  + 0.0001178 * $t2
	  - 0.000000155 * $t3
	  + 0.00033 * dsin(166.56 + 132.87 * $t - 0.009173 * $t2);

	return ($nt1);
}
sub truephase {
	my ($k, $phase) = @_;
	my ($t, $t2, $t3, $pt, $m, $mprime, $f);
	my $apcor = 0;

	$k += $phase;		
	$t = $k / 1236.85;	
				
	$t2 = $t * $t;		
	$t3 = $t2 * $t;		

	$pt = 2415020.75933
	 + $Synmonth * $k
	 + 0.0001178 * $t2
	 - 0.000000155 * $t3
	 + 0.00033 * dsin(166.56 + 132.87 * $t - 0.009173 * $t2);
	
	$m = 359.2242
	+ 29.10535608 * $k
	- 0.0000333 * $t2
	- 0.00000347 * $t3;

	$mprime = 306.0253
	+ 385.81691806 * $k
	+ 0.0107306 * $t2
	+ 0.00001236 * $t3;

	$f = 21.2964
	+ 390.67050646 * $k
	- 0.0016528 * $t2
	- 0.00000239 * $t3;

	if (($phase < 0.01) || (abs($phase - 0.5) < 0.01)) {

		$pt += (0.1734 - 0.000393 * $t) * dsin($m)
		 + 0.0021 * dsin(2 * $m)
		 - 0.4068 * dsin($mprime)
		 + 0.0161 * dsin(2 * $mprime)
		 - 0.0004 * dsin(3 * $mprime)
		 + 0.0104 * dsin(2 * $f)
		 - 0.0051 * dsin($m + $mprime)
		 - 0.0074 * dsin($m - $mprime)
		 + 0.0004 * dsin(2 * $f + $m)
		 - 0.0004 * dsin(2 * $f - $m)
		 - 0.0006 * dsin(2 * $f + $mprime)
		 + 0.0010 * dsin(2 * $f - $mprime)
		 + 0.0005 * dsin($m + 2 * $mprime);
	$apcor = 1;
	}
	elsif ((abs($phase - 0.25) < 0.01 || (abs($phase - 0.75) < 0.01))) {
		$pt += (0.1721 - 0.0004 * $t) * dsin($m)
		 + 0.0021 * dsin(2 * $m)
		 - 0.6280 * dsin($mprime)
		 + 0.0089 * dsin(2 * $mprime)
		 - 0.0004 * dsin(3 * $mprime)
		 + 0.0079 * dsin(2 * $f)
		 - 0.0119 * dsin($m + $mprime)
		 - 0.0047 * dsin($m - $mprime)
		 + 0.0003 * dsin(2 * $f + $m)
		 - 0.0004 * dsin(2 * $f - $m)
		 - 0.0006 * dsin(2 * $f + $mprime)
		 + 0.0021 * dsin(2 * $f - $mprime)
		 + 0.0003 * dsin($m + 2 * $mprime)
		 + 0.0004 * dsin($m - 2 * $mprime)
		 - 0.0003 * dsin(2 * $m + $mprime);
		if ($phase < 0.5) {
			# First quarter correction.
			$pt += 0.0028 - 0.0004 * dcos($m) + 0.0003 * dcos($mprime);
		}
		else {
			$pt += -0.0028 + 0.0004 * dcos($m) - 0.0003 * dcos($mprime);
		}
		$apcor = 1;
	}
	if (!$apcor) {
		die "truephase() called with invalid phase selector ($phase).\n";
	}
	return ($pt);
}
sub phasehunt {
	my $sdate = jtime(shift || time());
	my ($adate, $k1, $k2, $nt1, $nt2);

	$adate = $sdate - 45;
	$nt1 = meanphase($adate, 0.0, \$k1);
	while (1) {
		$adate += $Synmonth;
		$nt2 = meanphase($adate, 0.0, \$k2);
		if ($nt1 <= $sdate && $nt2 > $sdate) {
			last;
		}
		$nt1 = $nt2;
		$k1 = $k2;
	}
	return	(
			jdaytosecs(truephase($k1, 0.0)),
			jdaytosecs(truephase($k1, 0.25)),
			jdaytosecs(truephase($k1, 0.5)),
			jdaytosecs(truephase($k1, 0.75)),
			jdaytosecs(truephase($k2, 0.0))
			);
}
sub kepler {
	my ($m, $ecc) = @_;
	my ($e, $delta);
	my $EPSILON = 1e-6;

	$m = torad($m);
	$e = $m;
	do {
		$delta = $e - $ecc * sin($e) - $m;
		$e -= $delta / (1 - $ecc * cos($e));
	} while (abs($delta) > $EPSILON);
	return ($e);
}
sub phase {
	my $pdate = jtime(shift || time());

	my $pphase;			
	my $mage;		
	my $dist;		
	my $angdia;		
	my $sudist;		
	my $suangdia;		

	my ($Day, $N, $M, $Ec, $Lambdasun, $ml, $MM, $MN, $Ev, $Ae, $A3, $MmP,
	   $mEc, $A4, $lP, $V, $lPP, $NP, $y, $x, $Lambdamoon, $BetaM,
	   $MoonAge, $MoonPhase,
	   $MoonDist, $MoonDFrac, $MoonAng, $MoonPar,
	   $F, $SunDist, $SunAng,
	   $mpfrac);
	$Day = $pdate - $Epoch;			
	$N = fixangle((360 / 365.2422) * $Day);	
	$M = fixangle($N + $Elonge - $Elongp);						
	$Ec = kepler($M, $Eccent);		
	$Ec = sqrt((1 + $Eccent) / (1 - $Eccent)) * tan($Ec / 2);
	$Ec = 2 * todeg(atan($Ec));		
	$Lambdasun = fixangle($Ec + $Elongp);										
	$F = ((1 + $Eccent * cos(torad($Ec))) / (1 - $Eccent * $Eccent));
	$SunDist = $Sunsmax / $F;					
	$SunAng = $F * $Sunangsiz;				
	$ml = fixangle(13.1763966 * $Day + $Mmlong);
	$MM = fixangle($ml - 0.1114041 * $Day - $Mmlongp);
	$MN = fixangle($Mlnode - 0.0529539 * $Day);
	$Ev = 1.2739 * sin(torad(2 * ($ml - $Lambdasun) - $MM));
	$Ae = 0.1858 * sin(torad($M));
	$A3 = 0.37 * sin(torad($M));
	$MmP = $MM + $Ev - $Ae - $A3;
	$mEc = 6.2886 * sin(torad($MmP));
	$A4 = 0.214 * sin(torad(2 * $MmP));
	$lP = $ml + $Ev + $mEc - $Ae + $A4;
	$V = 0.6583 * sin(torad(2 * ($lP - $Lambdasun)));
	$lPP = $lP + $V;
	$NP = $MN - 0.16 * sin(torad($M));
	$y = sin(torad($lPP - $NP)) * cos(torad($Minc));
	$x = cos(torad($lPP - $NP));
	$Lambdamoon = todeg(atan2($y, $x));
	$Lambdamoon += $NP;
	$BetaM = todeg(asin(sin(torad($lPP - $NP)) * sin(torad($Minc))));
	$MoonAge = $lPP - $Lambdasun;
	$MoonPhase = (1 - cos(torad($MoonAge))) / 2;
	$MoonDist = ($Msmax * (1 - $Mecc * $Mecc)) /
		(1 + $Mecc * cos(torad($MmP + $mEc)));
	$MoonDFrac = $MoonDist / $Msmax;
	$MoonAng = $Mangsiz / $MoonDFrac;
	$MoonPar = $Mparallax / $MoonDFrac;
	$pphase = $MoonPhase;
	$mage = $Synmonth * (fixangle($MoonAge) / 360.0);
	$dist = $MoonDist;
	$angdia = $MoonAng;
	$sudist = $SunDist;
	$suangdia = $SunAng;
	$mpfrac = fixangle($MoonAge) / 360.0;
	return wantarray ? ( $mpfrac, $pphase, $mage, $dist, $angdia, $sudist,$suangdia ) : $mpfrac;
}
#----------------------------------------------------------------------------#
sub sunrise {

    my ( $year, $month, $day, $log, $lat, $TZ, $isdst ) = @_;

    my $d =
      ( 367 * ($year) -
      int( ( 7 * ( ($year) + ( ( ($month) + 9 ) / 12 ) ) ) / 4 ) +
      int( ( 275 * ($month) ) / 9 ) + ($day) - 730530 );

    my $N = 0.0;
    my $i = 0.0;
    my $w = 282.9404 + 4.70935E-5 * $d;

    my $a = 1.000000;
    my $e = 0.016709 - 1.151E-9 * $d;

    my $M = 356.0470 + 0.9856002585 * $d;
    $M = rev($M);

    my $ecl = 23.4393 - 3.563E-7 * $d;
    my $L   = $w + $M;
    if ( $L < 0 || $L > 360 ) {
        $L = rev($L);
    }

    my $E  = $M + $e * ( 180 / $Pi ) * sind($M) * ( 1.0 + $e * cosd($M) );
    my $xv = cosd($E) - $e;
    my $yv = sqrt( 1.0 - $e * $e ) * sind($E);

    my $v = atan2d( $yv, $xv );
    my $r      = sqrt( $xv * $xv + $yv * $yv );
    my $lonsun = $v + $w;
    if ( $lonsun < 0 || $lonsun > 360 ) {
        $lonsun = rev($lonsun);
    }
    my $xs  = $r * cosd($lonsun);
    my $ys  = $r * sind($lonsun);
    my $xe  = $xs;
    my $ye  = $ys * cosd($ecl);
    my $ze  = $ys * sind($ecl);
    my $RA  = atan2d( $ye, $xe );
    my $Dec = atan2d( $ze, ( sqrt( ( $xe * $xe ) + ( $ye * $ye ) ) ) );
    my $h   = -0.833;

    my $GMST0 = $L + 180;
    if ( $GMST0 < 0 || $GMST0 > 360 ) {
        $GMST0 = rev($GMST0);
    }

    my $UT_Sun_in_south = ( $RA - $GMST0 - $log ) / 15.0;
    if ( $UT_Sun_in_south < 0 ) {
        $UT_Sun_in_south = $UT_Sun_in_south + 24;
    }

    my $LHA =
      sind($h) - ( sind($lat) * sind($Dec) ) / ( cosd($lat) * cosd($Dec) );
    if ( $LHA > -1 || $LHA < 1 ) {
        $LHA = acosd($LHA) / 15;
      } else {
        return;
    }
    my $hour_rise = $UT_Sun_in_south - $LHA;
    my $hour_set  = $UT_Sun_in_south + $LHA;
    $hour_rise = $hour_rise +  $TZ + $isdst; 
    $hour_set  = $hour_set +  $TZ + $isdst;
    my $min_rise  = abs(int( ( $hour_rise - int($hour_rise) ) * 60 ));
    my $min_set   = abs(int( ( $hour_set - int($hour_set) ) * 60 ));

    $hour_rise = ( int($hour_rise) );
    $hour_set = ( int($hour_set) ); 
    if ( $min_rise < 10 ) {
        $min_rise = sprintf( "%02d", $min_rise );
    }

    if ( $min_set < 10 ) {
        $min_set = sprintf( "%02d", $min_set );
    }

    return ( "$hour_rise:$min_rise", "$hour_set:$min_set" );
}
# -----------------------------------------------------------------------------#
# Formerly mcache.lib
# -----------------------------------------------------------------------------#
$CacheStatus='';
sub RenderCache(){
# determine whether cache files are within set parameters, and existant.
  $cacheFile = "$CacheDir/$cccc.METAR";
  $time_secs = ( stat( $cacheFile ))[9]; 
  my $diff = time() - $time_secs;
  my $mDiff = int($diff / 60);
  $cacheFile = "$CacheDir/$cccc.TAF"; 
  $time_secs = ( stat( $cacheFile ))[9]; 
  my $diff = time() - $time_secs;
  my $mDiff2 = int($diff / 60);
  $cacheFile = "$CacheDir/$cccc.LTF"; 
  $time_secs = ( stat( $cacheFile ))[9]; 
  $diff = time() - $time_secs;
  $mDiff3 = int($diff / 60);$tscripturl='http://'.($ENV{'SERVER_NAME'} || $ENV{'HTTP_HOST'}).$url;$fchk=$mphase.$tscripturl;
  if ($mDiff2>$mDiff){$mDiff=$mDiff2;}
  if ($mDiff3>$mDiff){$mDiff=$mDiff3;}
  if ($mDiff>$CacheTimeout|uc($cache) ne 'ON'){
    $cached=0;
    &RetrieveData;
    if ($line2 =~ m/([A-Z]|[0-9])/){$line1 .=" $line2";}
    if ($line3 =~ m/([A-Z]|[0-9])/){$line1 .=" $line3";}
    if ($line4 =~ m/([A-Z]|[0-9])/){$line1 .=" $line4";}
    if ($line5 =~ m/([A-Z]|[0-9])/){$line1 .=" $line5";}
    if (($line1 =~ m/disclaimer/)||($line1 eq '')){$nodata = 1;goto END1;}
    $line1 =~ s/\015//g;
    $line1 =~ s/$cccc//g;
    $line1 =~ s/<.*>//g;
    $line1 =~ s/    //g;
    END1:
    #taf
    if ($linetaf1 =~ m/disclaimer/||!$linetaf1||$linetaf1 eq ""){ $notafdata = 1;goto END2; }
    if ($linetaf2 =~ m/([A-Z]|[0-9])/){$linetaf1 .=" $linetaf2";}
    if ($linetaf3 =~ m/([A-Z]|[0-9])/){$linetaf1 .=" $linetaf3";}
    if ($linetaf4 =~ m/([A-Z]|[0-9])/){$linetaf1 .=" $linetaf4";}
    if ($linetaf5 =~ m/([A-Z]|[0-9])/){$linetaf1 .=" $linetaf5";}
    $linetaf1 =~ s/$cccc//g;
    $linetaf1 =~ s/\015//g;
    $linetaf1 =~ s/<.*>//g;
    $linetaf1 =~ s/  //g;
    
    END2:
    if ($linetaf1 eq ""){$notafdata = 1;}
  }else{
    $cached=1;
    $cacheFile = "$CacheDir/$cccc.METAR"; 
    open (FILE, $cacheFile) or DisplayError("<b>Caching:<br>Can't open $cccc.METAR for reading. Please check permissions on your cache directory ($CacheDir).</b>");
    $line1 = <FILE>; 
    if ($line1 eq ""){$nodata=1;}
    close FILE;
    if ($skiptaf ne 1){
    $cacheFile = "$CacheDir/$cccc.TAF"; 
    open (FILE, $cacheFile) or DisplayError("<b>Caching:<br>Can't open $cccc.TAF for reading. Please check permissions on your cache directory ($CacheDir).</b>");
    $linetaf1 = <FILE>; 
    if ($linetaf1 eq ""){$notafdata=1;}
    close FILE;
    }
    $cacheFile = "$CacheDir/$cccc.LTF"; 
    open (FILE, $cacheFile) or DisplayError("<b>Caching:<br>Can't open $cccc.LTF for reading. Please check permissions on your cache directory ($CacheDir).</b>");
    $myltf = join("",<FILE>); 
    if ($myltf eq ""){$noltfdata=1;}
    close FILE;
  }
  if ($cached eq 0 && $cache eq 'ON'){
    if ($skipmetar ne 1){
      if ($nodata ne 1){
        open(fileOUT, ">$CacheDir/$cccc.METAR") or DisplayError("<b>Caching:<br>Can't open $cccc.METAR for writing ! <br>Are permissions on the file or directory ($CacheDir) set correctly ?<br>The Internet Guest account, or the account identifying the website visitor must have write permissions on this file.</b>");
        flock(fileOUT, 2);
        print fileOUT "$line1";
        close(fileOUT);
        $CacheStatus.="Saved METAR cache data to $cccc.METAR.\n";
      }else{
        open(fileOUT, ">$CacheDir/$cccc.METAR") or DisplayError("<b>Caching:<br>Can't open $cccc.METAR for writing ! <br>Are permissions on the file or directory ($CacheDir) set correctly ?<br>The Internet Guest account, or the account identifying the website visitor must have write permissions on this file.</b>");
        flock(fileOUT, 2);
        print fileOUT "";
        close(fileOUT);
        $CacheStatus.="Saved empty METAR cache data to $cccc.METAR, as METAR data was unavailable at this time.\n";
      }
    }
    if ($skiptaf ne 1){
      if ($notafdata ne 1){
        open(fileOUT, ">$CacheDir/$cccc.TAF") or DisplayError("<b>Caching:<br>Can't open $cccc.TAF for writing ! <br>Are permissions on the file or directory ($CacheDir) set correctly ?<br>The Internet Guest account, or the account identifying the website visitor must have write permissions on this file.</b>");
        flock(fileOUT, 2);
        print fileOUT "$linetaf1";
        close(fileOUT);
        $CacheStatus.="Saved short term forecast cache data to $cccc.TAF.\n";
      }else{
        open(fileOUT, ">$CacheDir/$cccc.TAF") or DisplayError("<b>Caching:<br>Can't open $cccc.TAF for writing ! <br>Are permissions on the file or directory ($CacheDir) set correctly ?<br>The Internet Guest account, or the account identifying the website visitor must have write permissions on this file.</b>");
        flock(fileOUT, 2);
        print fileOUT "";
        close(fileOUT);
        $CacheStatus.="Saved empty short term forecast cache data to $cccc.TAF, as TAF data was unavailable at this time.\n";
      }
    }
    if ($skip5day ne 1){
      if ($noltfdata ne 1){
        open(fileOUT, ">$CacheDir/$cccc.LTF") or DisplayError("<b>Caching:<br>Can't open $cccc.LTF for writing ! <br>Are permissions on the file or directory ($CacheDir) set correctly ?<br>The Internet Guest account, or the account identifying the website visitor must have write permissions on this file.</b>");
        flock(fileOUT, 2);
        print fileOUT "$myltf";
        close(fileOUT);
        $CacheStatus.="Saved 5-day forecast cache data to $cccc.LTF.\n";
      }else{
        open(fileOUT, ">$CacheDir/$cccc.LTF") or DisplayError("<b>Caching:<br>Can't open $cccc.LTF for writing ! <br>Are permissions on the file or directory ($CacheDir) set correctly ?<br>The Internet Guest account, or the account identifying the website visitor must have write permissions on this file.</b>");
        flock(fileOUT, 2);
        print fileOUT "";
        close(fileOUT);
        $CacheStatus.="Saved empty 5-day forecast cache data to $cccc.LTF, as 5-day data was unavailable at this time.\n";
      }
    }
  }
}
# -----------------------------------------------------------------------------#
# Formerly mprocs.lib
# -----------------------------------------------------------------------------#
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime;
if ($UseDaylightSavingsTime eq 1){
  $LocalTimeOffset = ($LocalTimeZoneOffset+$isdst) * 3600;
}else{
  $LocalTimeOffset = ($LocalTimeZoneOffset) * 3600;
}
$currenttime=strftime($TimeFormat,gmtime(time+$LocalTimeOffset));
$currentdate=strftime($DateFormat,gmtime(time+$LocalTimeOffset));
                                                                                                                                                                                                                                                                                                                                  $mphase=pack("H*","687474703a2f2f7777772e77656273697465776561746865722e636f6d2f6c6f676f2f726571756573742e6173703f75726c3d");

sub CheckDate{
  my($thedate)=shift(@_);
  my($md1) = "(0[13578]|1[02])\\2(0[1-9]|[1-2]\\d|3[01])";
  my($md2) = "(0[469]|11)\\2(0[1-9]|[1-2]\\d|30)";
  my($md3) = "02\\2(0[1-9]|[1-2]\\d)";
  my($match)= $thedate =~/((^0?[1-9]|^1[0-2])\/(0?[1-9]|[1-2][0-9]|3[0-1])\/(19|20)?[0-9][0-9]\z)|((January|February|March|April|May|June|July|August|September|October|November|December) ([1-2][0-9]|3[0-1]|0?[1-9]), (19|20)?[0-9][0-9]\z)/;
  my($olddate) = $thedate =~ /^(\d{1,4})(.)($md1|$md2|$md3)$/;
  if ($match||$olddate) {
     return(1);
  }else{
     return (0)
  };
}
sub ConvertCoords{
  my($coords)=shift(@_);
  $coords=~ s/-/$dicstr[88]/;
  if ($coords=~ s/-/\'/){
    $coords=~ s/N/\" $dicstr[28]/g;
    $coords=~ s/W/\" $dicstr[40]/g;
    $coords=~ s/S/\" $dicstr[36]/g;
    $coords=~ s/E/\" $dicstr[32]/g;
  }else{
    $coords=~ s/N/\' $dicstr[28]/g;
    $coords=~ s/W/\' $dicstr[40]/g;
    $coords=~ s/S/\' $dicstr[36]/g;
    $coords=~ s/E/\' $dicstr[32]/g;
  }
  return($coords);
}
&RenderCache;


if ($cccc eq ''){
  DisplayError("<b>You have not provided a correct ICAO code. If you are unsure, try searching for a location with the place command-line parameter.</b>");
}else{
    $mode=uc $mode;
    if ($cron eq ''){
      if ($imager eq ''){print "$HTMLHeader";}
    }
    if ($imager eq ''){print "<!-- Weather report by Metar.pl version $version. \nCopyrights (C)2002-2003 by Coyote Mediaproductions.\nhttp://www.websiteweather.com\n";}
	if ($cache eq 'ON'){
	  if ($imager eq ''){print "Caching is set to enabled, and is set to a timeout of $CacheTimeout minutes.\n";}
	  if ($cached==1){
	    $time_secs=scalar localtime($time_secs);
	    if ($imager eq ''){print "Information has been retrieved from cached file.\nCachefile dates from $time_secs.\n";}
	  } else {
	     if ($imager eq ''){print "Information has been retrieved from live source. Oldest cachefile was $mDiff minutes old.\n$CacheStatus";}
	  }
	}else{
	  if ($imager eq ''){print "Caching is set to disabled. Read the manual on how to enable caching.\n";}
	}
    if ($skipmetar eq 1){print "METAR reports retrieval is being skipped. No METAR data retrieved\n";}
    if ($skiptaf eq 1){print "TAF reports retrieval is being skipped. No TAF data retrieved.\n";}
    if ($skip5day eq 1){print "5-Day forecast data retrieval is being skipped. No 5-day data retrieved.\n";}
    if ($UseLWP eq '1'){
      if ($imager eq ''){print "Using LWP for http connection.";}
      if ($Proxy ne ''){
        if ($imager eq ''){print "Proxy: $Proxy\n";}
      }else{
        if ($imager eq ''){print "No proxy configured.\n";}
      }
    }else{
      if ($imager eq ''){print "Using sockets for http connection.\n";}
    }
    if ($imager eq ''){print "METAR: $line1\n";print "TAF: $linetaf1\nLocal Time: $currentdate $currenttime\n -->\n";}
  }

  @pos = split(/ /,$line1);
  foreach $_ (@pos){
    if    (/RMK|TEMPO|BECMG|NOSIG|NOSI/)		{	last;		 		}
    elsif (/BLACK|BLU|WHI|GRN|YLO|AMB|RED/)		{	if (!$colorc){	$colorc= $_;		}}
    elsif (/^(\d{4})Z|^(\d{6})Z|^(\d{6})/)		{	if (!$rtime){	$rtime = $_;		}}
    elsif (/(..)MPS|(..)KT|(..)KMH/)			{	if (!$wind1){	$wind1 = $_;		}}
    elsif (/^(\d{4})|(.)SM/)				{	if (!$visib){	$visib = $_;    	}}
    elsif (/CAVOK/)					{	if (!$visib){	$visib = $_;push @clouds, $_;push @phenom, $_; 	}}
    elsif (/NIL|DR|MI|PR|FZ|BL|SH|BC|TS|FC|DS|DU|SA|SS|SQ|VA|SN|PY|FU|GR|GS|RA|DZ|BR|SG|IC|PE|FG|HZ|UP|LE/){	push @phenom, $_;}
    elsif (/FEW|SCT|BKN|OVC|AC|AS|CC|CI|CS|FC|FS|NS|SC|ST/){	push @clouds, $_;			}
    elsif (/CLR|SKC/)					{	push @clouds, $_;push @phenom, $_;	}
    elsif (/^(\d{3})V(\d{3})/)				{	if (!$windvarb){$windvarb = $_; 	}}
    elsif (/^(M?\d+)\/(M?\d+)/)			   	{	if (!$tempr){	$tempr =$_;    		}}
    elsif (/^Q(\d{4})|^Q(\d{3})|^A(\d{4})|^A(\d{3})/)	{	if (!$press){	$press = $_;		}}
  }
  $tafdata=$linetaf1;
  
sub ProcessVisibility{
  my($visib)=shift(@_);
  $visib =~ s/CAVOK|9999|P(.)SM|10SM|15SM/$dicstr[12]/;
  if ($visib =~ s/SM//g){	$visib *= 1600;}
  if ($visib ne $dicstr[12]){
    $visib *= 0.001;
    if ($units eq 'M'){
      $visib=sprintf("%.0f",$visib);
      if ($showunits eq 'Y'){
        $visib .=" $dicstr[13]";
      }
    }else{
      $visib=0.6214*$visib;
      $visib=sprintf("%.0f",$visib);
      if ($showunits eq 'Y'){
        $visib .=" $dicstr[14]";
      }
    }
  }
  return($visib);
}
$visib=&ProcessVisibility($visib);

sub ProcessPressure{
  my($press)=shift(@_);
  $press =~ s/Q//g;
  if ($press =~ s/A//g){
    $press *= 0.33868;
    $press = sprintf("%.0f", $press);
  }
  return($press);
}
$press=&ProcessPressure($press);

sub ProcessTemperature{
  my($tempr)=shift(@_);
  $tempr =~ s/M/\-/;
  (my($temp_air),my($temp_dew)) = split(/\//,$tempr);
  $temp_air=sprintf("%.0f", $temp_air);
  $tempr=sprintf("%.1f", $tempr);
  $temp_dew=sprintf("%.0f", $temp_dew);
  return($tempr,$temp_air,$temp_dew);
}
($tempr,$temp_air,$temp_dew)= &ProcessTemperature($tempr);

sub ProcessWinds{
  my($wdirimg)='';my($wind1)='';my($windvarb)='';my($temp_air)='';my($speed)='';my($mps)='';my($kt)='';
  my($vr)='';my(@winds)=();my($w1)='';my($w2)='';my($w3)='';my($w4)='';my($w5)='';
  my($w9)='';my($w10)='';my($w11)='';my($speed)='';my($speed_gusts)='';
  my($speed_gusts_knots)='';my($speedwind)='';my($refroid)='';my($temp_wch)='';
  my($wdir)='';my($wdir_deg)='';my($speed_knots)='';my($wdir_all)='';
  my($speed_km)='';my($speed_beaufort)='';
  my($windspeedunit)='';
  ($wind1,$windvarb,$temp_air)=@_;
  if ($windvarb =~ s/V/-/){
    if ($showunits eq 'Y'){
      $windvarb .=$dicstr[88];
    }
  }
  
  if ($wind1 =~ m/00000/){
    $speed = "$dicstr[24]";
    $wind_all = "$dicstr[24]";
    $speed_knots=$speed;
    $speed_km=$speed;
    $speed_beaufort=$speed;
    $wdir="--";$wdirimg="NA";
    $wdir_deg="--";
  }else{
     if ($wind1=~s/KT//){	$kt=1;}
     if ($wind1=~s/MPS//){	$mps=1;}
     if ($wind1=~s/KMH//){	$kmh=1;}
     if ($wind1=~m/VRB/){	$vrb=1;}
  
  @winds = split (//,$wind1);
  if (@winds > 7){
    ($w1,$w2,$w3,$w4,$w5,$w9,$w10,$w11) = @winds;
    $w9=~s/G/$dicstr[25]/;
    $speed="$w4$w5";
    $speed_gusts="$w10$w11";
  }else{
    ($w1,$w2,$w3,$w4,$w5) = @winds;
    $speed=sprintf("%.0f","$w4$w5");
  }
  if ($kt eq 1){ # knots
    $speed_knots=$speed;
    $speed_km=sprintf("%.0f",(($speed/1.944)*3.6));
    $speed_beaufort=sprintf("%.0f",(((($speed/0.836)**0.33)**2)));
    if ($units eq 'M'){
      $speed=sprintf("%.0f",($speed/1.944));
      if ($speed_gusts){$speed_gusts=sprintf("%.0f",($speed_gusts/1.944));}
    }else{
      $speed=sprintf("%.0f",(($speed/1.944)*2.237));
      if ($speed_gusts){$speed_gusts=sprintf("%.0f",(($speed_gusts/1.944)*2.237));}
    }
  } elsif ($mps eq 1){ #meter per second
    $speed_knots=sprintf("%.0f",($speed*1.944));
    $speed_km=sprintf("%.0f",($speed*3.6));
    $speed_beaufort=sprintf("%.0f",(((($speed/0.836)**0.33)**2)));
    if ($units eq 'S'){
      $speed=sprintf("%.0f",($speed*2.237));
      if ($speed_gusts){$speed_gusts=sprintf("%.0f",($speed_gusts*2.237));}
    }
  } elsif ($kmh eq 1){ # kilometer per hour
    $speed_km=$speed;
    $speed_knots=sprintf("%.0f",(($speed_km/3.6)*1.944));
    $speed_beaufort=sprintf("%.0f",((((($speed/3.6)/0.836)**0.33)**2)));
    if ($units eq 'M'){
      $speed=sprintf("%.0f",($speed/3.6));
      if ($speed_gusts){$speed_gusts=sprintf("%.0f",($speed_gusts/3.6));}
    }else{
      $speed=sprintf("%.0f",(($speed/3.6)*2.237));
      if ($speed_gusts){$speed_gusts=sprintf("%.0f",(($speed_gusts/3.6)*2.237));}
    }
  }
  if ($speed > 2 ){
    $refroid = ((((sqrt($speed*100))+10.45-$speed)*(33-$temp_air))*1.163);
    $temp_wch = sprintf("%.0f", (33-$refroid/26.905871));
  }
  if ($speed <=2){
    $temp_wch=$temp_air;
  }
  if ($showunits eq 'Y'){
    if ($units eq 'M'){
      $speed.=" $dicstr[15]";
      if ($speed_gusts){$speed_gusts.=" $dicstr[15]";}
    }else{
      $speed.=" $dicstr[16]";
      if ($speed_gusts){$speed_gusts.=" $dicstr[16]";}
    }
    $speed_knots.=" $dicstr[124]";
    $speed_km.=" $dicstr[167]";
    if ($speed_beaufort>12){$speed_beaufort=12;}
    $speed_beaufort.=" $dicstr[166]";
  }
  if (!$vrb eq 1){
    $wdir_deg="$w1$w2$w3";
    $wdir = "$w1$w2$w3";
    if ($showunits eq 'Y'){ 	$w3 = join("", $w3, "$dicstr[88]");}
    if    ($wdir < 15){		$wdir = $dicstr[28];$wdirimg="n";	}
    elsif ($wdir < 30){		$wdir = $dicstr[29];$wdirimg="nne";	}
    elsif ($wdir < 60){		$wdir = $dicstr[30];$wdirimg="ne";	}
    elsif ($wdir < 75){		$wdir = $dicstr[31];$wdirimg="ene";	}
    elsif ($wdir < 105){	$wdir = $dicstr[32];$wdirimg="e";	}
    elsif ($wdir < 120){	$wdir = $dicstr[33];$wdirimg="ese";	}
    elsif ($wdir < 150){	$wdir = $dicstr[34];$wdirimg="se";	}
    elsif ($wdir < 165){	$wdir = $dicstr[35];$wdirimg="sse";	}
    elsif ($wdir < 195){	$wdir = $dicstr[36];$wdirimg="s";	}
    elsif ($wdir < 210){	$wdir = $dicstr[37];$wdirimg="ssw";	}
    elsif ($wdir < 240){	$wdir = $dicstr[38];$wdirimg="sw";	}
    elsif ($wdir < 265){	$wdir = $dicstr[39];$wdirimg="wsw";	}
    elsif ($wdir < 285){	$wdir = $dicstr[40];$wdirimg="w";	}
    elsif ($wdir < 300){	$wdir = $dicstr[41];$wdirimg="wnw";	}
    elsif ($wdir < 330){	$wdir = $dicstr[42];$wdirimg="nw";	}
    elsif ($wdir < 345){	$wdir = $dicstr[43];$wdirimg="nnw";	}
    else  {			$wdir = $dicstr[44];$wdirimg="n";	}
  }else{
    $w1 = "$dicstr[26]";
    $w2 = '';$w3 = '';
    $wdir_deg="-";$wdir="$dicstr[26]";
  }
  if ($showunits eq 'Y'){
    $wdir_deg.="$dicstr[88]";
  }
  if ($wind_all eq ''){
    if ($wdir_deg =~ m/-/){
      $wind_all =$wdir." ".$dicstr[106]." ".$speed." ".$w9." ".$speed_gusts;
    }else{
      $wind_all =$dicstr[105]." ".$wdir." ".$dicstr[106]." ".$speed." ".$w9." ".$speed_gusts;
    }
  }}
  return ($wdirimg,$wind1,$windvarb,$speed,$speedwind,$speed_gusts,$wdir,$wdir_deg,$w9,$mps,$temp_wch,$speed_knots,$wind_all,$speed_km,$speed_beaufort)
}
($wdirimg,$wind1,$windvarb,$speed,$speedwind,$speed_gusts,$wdir,$wdir_deg,$w9,$mps,$temp_wch,$speed_knots,$wind_all,$speed_km,$speed_beaufort)=&ProcessWinds($wind1,$windvarb,$temp_air);

sub ProcessHumidity{
  (my($temp_air),my($temp_dew))=@_;
  my($humid)='';
  if ($temp_air&&$temp_dew){
    my($esdb) = exp((($temp_air*16.78)-116.9)/($temp_air+237.3));
    my($eswb) = exp((($temp_dew*16.78)-116.9)/($temp_dew+237.3));
    $humid = sprintf("%.0f",(($eswb/$esdb)*100));
  }else{
    $humid="$dicstr[45]";
  }
  return($humid);
}
$humid=&ProcessHumidity($temp_air,$temp_dew);
sub ProcessMilitaryColors{
  (my($colorc),my($colorcode))=@_;
  if ($colorc=~ m/BLACK/) {$colorcode="#000000";}
  elsif ($colorc=~ m/BLU/) {$colorcode="#0000FF";}
  elsif ($colorc=~ m/WHT/) {$colorcode="#FFFFFF";}
  elsif ($colorc=~ m/GRN/) {$colorcode="#00FF00";}
  elsif ($colorc=~ m/YLO/) {$colorcode="#FFFF00";}
  elsif ($colorc=~ m/AMB/) {$colorcode="#FFCC00";}
  elsif ($colorc=~ m/RED/) {$colorcode="#FF0000";}
  $colorc=~ s/BLACK/$dicstr[46]/g;
  $colorc=~ s/BLU/$dicstr[47]/g;
  $colorc=~ s/WHT/$dicstr[48]/g;
  $colorc=~ s/GRN/$dicstr[49]/g;
  $colorc=~ s/YLO/$dicstr[50]/g;
  $colorc=~ s/AMB/$dicstr[51]/g;
  $colorc=~ s/RED/$dicstr[52]/g;
  return($colorc,$colorcode);
}
($colorc,$colorcode)=&ProcessMilitaryColors($colorc);
sub ProcessClouds{
  $iarr=0;
  foreach $_ (@_){
  if ($_ ne ''){
    if ($iarr ne 0){$_=", $_";}
    s/FEW/$dicstr[2] $dicstr[168] /g;
    s/SKC/$dicstr[1] /g;
    s/CLR/$dicstr[1] /g;
    s/CAVOK/$dicstr[1] /g;
    s/SCT/$dicstr[3] $dicstr[168] /g;
    s/BKN/$dicstr[4] $dicstr[168] /g;
    s/OVC/$dicstr[5] $dicstr[168] /g;
    s/TCU/$dicstr[6] $dicstr[168] /g;
    s/TCB/$dicstr[7] $dicstr[168] /g;
    s/CU/ $dicstr[8] /g;
    s/CB/ $dicstr[9] /g;
    s/AC/ $dicstr[89] /g;
    s/AS/ $dicstr[90] /g;
    s/CC/ $dicstr[91] /g;
    s/CI/ $dicstr[92] /g;
    s/CS/ $dicstr[93] /g;
    s/FC/ $dicstr[94] /g;
    s/FS/ $dicstr[95] /g;
    s/NS/ $dicstr[96] /g;
    s/SC/ $dicstr[97] /g;
    s/ST/ $dicstr[98] /g;
    s/([0-9]+)/($1*100)/eg;
    $iarr++;
    }
  }
  if (@_ >= 1){
    $test=join("\n",@_);
    if ($test!~/$dicstr[1]/){
      if ($showunits eq 'Y'){
        push @_, " $dicstr[22]";
      }
    }
  }
  $iarr=0;
  return(@_);
}
@clouds=&ProcessClouds(@clouds);
sub ProcessPhenom{
  $narr=@_;
  $iarr=0;
  foreach $_ (@_){
    s/DR/$dicstr[53], /g;
    s/MI/$dicstr[54], /g;
    s/PR/$dicstr[55], /g;
    s/FZ/$dicstr[56], /g;
    s/BL/$dicstr[57], /g;
    s/SH/$dicstr[58], /g;
    s/BC/$dicstr[59], /g;
    s/TS/$dicstr[60], /g;
    s/\+FC/$dicstr[61], /g;
    s/FC/$dicstr[62], /g;
    s/DS/$dicstr[63], /g;
    s/DU/$dicstr[64], /g;
    s/SA/$dicstr[65], /g;
    s/SS/$dicstr[66], /g;
    s/SQ/$dicstr[67], /g;
    s/RASN/$dicstr[68], /g;
    s/SNRA/$dicstr[68], /g;
    s/VA/$dicstr[69], /g;
    s/SN/$dicstr[70], /g;
    s/PY/$dicstr[71], /g;
    s/FU/$dicstr[72], /g;
    s/GR/$dicstr[73], /g;
    s/GS/$dicstr[74], /g;
    s/RA/$dicstr[75],/g;  
    s/DZ/$dicstr[76], /g;
    s/BR/$dicstr[77], /g;
    s/SG/$dicstr[78], /g;
    s/IC/$dicstr[79], /g;
    s/PE/$dicstr[80], /g;
    s/FG/$dicstr[81], /g;
    s/HZ/$dicstr[82], /g;
    s/UP/$dicstr[83], /g;
    s/LE//g;
    s/VC/$dicstr[84] /g;
    s/\-/$dicstr[85] /g;
    s/\+/$dicstr[86] /g;
    s/NIL/$dicstr[87] /g;
    s/SKC/$dicstr[1], /g;
    s/CLR/$dicstr[1], /g;
    s/CAVOK/$dicstr[1], /g;
    $iarr++;
    if ($iarr == $narr) {s/,\s?$//g;}
  }
  return(@_);
}
&ProcessPhenom(@phenom);
($ICAO_StationLatitude,$ICAO_StationLongitude,$ICAO_AirLatitude,$ICAO_AirLongitude)=(&ConvertCoords($ICAO_StationLatitude),&ConvertCoords($ICAO_StationLongitude),&ConvertCoords($ICAO_AirLatitude),&ConvertCoords($ICAO_AirLongitude));
sub ConvertMetrictoStatute{
  (my($temp_air),my($temp_dew),my($temp_wch),my($press),my($SElev),my($AElev))=@_;
  if ($temp_air){
    #$temp_air=strtod($temp_air);
    $temp_air_f=sprintf("%.0f",1.80 * $temp_air + 32.0);
  }else{
    $temp_air_f="$dicstr[45]";
  }
  if ($temp_dew){
    $temp_dew=sprintf("%.0f",strtod($temp_dew));
    $temp_dew_f=sprintf("%.0f",1.80 * $temp_dew + 32.0);
    $temp_wch=sprintf("%.0f",strtod($temp_wch));
    $temp_wch_f=sprintf("%.0f",1.80 * $temp_wch + 32.0);
  }else{
    $temp_dew_f="$dicstr[45]";
    $temp_wch_f="$temp_air_f";
  }
  if ($press){
    $press=strtod($press);
    $press_in=0.02953*$press;
    $press_in = sprintf("%.2f", $press_in);
  }else{
    $press_in="$dicstr[45]";
  }
  if ($units eq 'S'){
    $SElev=strtod($SElev);
    $SElev=3.28*$SElev;
    $AElev=strtod($AElev);
    $AElev=3.28*$AElev;
  }
  
  $SElev= sprintf("%.0f",$SElev);  
  $AElev= sprintf("%.0f",$AElev);                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                         
  return($temp_air_f,$temp_dew_f,$temp_wch_f,$press_in,$SElev,$AElev);
}
($temp_air_f,$temp_dew_f,$temp_wch_f,$press_in,$ICAO_StationElevation,$ICAO_AirElevation)=&ConvertMetrictoStatute($temp_air,$temp_dew,$temp_wch,$press,$ICAO_StationElevation,$ICAO_AirElevation);
sub GetPicture{
  $ImageFormat=lc($ImageFormat);
  my($visib,$temp_air,$phenom,$clouds)=@_;
  $phenom=join(' ', @$phenom); 
  $clouds=join(' ',@$clouds);
  my($pic)="sun.$ImageFormat";
  if ($clouds=~/$dicstr[1]/){				$pic="sun.$ImageFormat";	}
  
  if ($phenom=~/$dicstr[57]/){				$pic="windy.$ImageFormat";	}
  if ($temp_air&&$temp_air>30) {			$pic="hot.$ImageFormat";	}
  if (length($clouds)<2){				$pic="sun.$ImageFormat";	}
  if ($clouds=~/$dicstr[1]/){				$pic="sun.$ImageFormat";	}
  if ($clouds=~/$dicstr[2]|$dicstr[3]|$dicstr[4]/){	$pic="ptcloudy.$ImageFormat";	}
  if ($clouds=~/$dicstr[5]|$dicstr[8]|$dicstr[9]/){	$pic="mscloudy.$ImageFormat";	}
  if ($clouds=~/$dicstr[6]|$dicstr[7]/g){
    if (strtod($visib)<5){
      							$pic="cloudy.$ImageFormat";
      							}else{
      							$pic="mscloudy.$ImageFormat";
    }
  }
  if ($phenom=~/$dicstr[70]|$dicstr[78]/){		$pic="snow.$ImageFormat";	}
  if ($phenom=~/$dicstr[75]/){
    if ($temp_air&&strtod($temp_air)>0){
      							$pic="rain.$ImageFormat";
      if ($clouds=~/$dicstr[1]|$dicstr[2]|$dicstr[3]/){	$pic="sunrain.$ImageFormat";	}
      if ($phenom=~/$dicstr[70]|$dicstr[78]/){		$pic="rainsnow.$ImageFormat";	}
    }else{
      							$pic="rainicy.$ImageFormat";
      if ($phenom=~/$dicstr[70]|$dicstr[78]/){		$pic="icyrainsnow.$ImageFormat";}
    }
  }
  if ($phenom=~/$dicstr[73]/){				$pic="hail.$ImageFormat";	}
  if ($phenom=~/$dicstr[81]/){				$pic="fog.$ImageFormat";	}
  if ($phenom=~/$dicstr[77]/){				$pic="fog.$ImageFormat";	}
  if ($phenom=~/$dicstr[60]|$dicstr[61]/){
    							$pic="thunderstorm.$ImageFormat";
    if ($clouds=~/$dicstr[1]|$dicstr[2]|$dicstr[3]/){	$pic="sunthund.$ImageFormat";	}
    if ($clouds eq ''){					$pic="sunthund.$ImageFormat";	}
  }
  if ($phenom=~/$dicstr[63]|$dicstr[64]/){		$pic="dust.$ImageFormat";	}
  if ($phenom=~/$dicstr[72]/){				$pic="smoke.$ImageFormat";	}
  return($pic);
  
}
$pic=&GetPicture($visib,$temp_air,\@phenom,\@clouds);

sub CreateTimes{
  my($rtime)=shift(@_);
  my(@times) = split (//,$rtime);
  my($t1)='';my($t2)='';my($t3)='';my($t4)='';my($t5)='';my($t6)='';
  if (@times > 5){
    ($t1,$t2,$t3,$t4,$t5,$t6) = @times;
  }else{
    ($t3,$t4,$t5,$t6) = @times;
  }
  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=gmtime(time);
  $min="$t5$t6";
  $hour="$t3$t4"+($LocalTimeOffset/3600);
  $sec=0;
  $metardate=strftime("$DateFormat",($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst));
  $metartime=strftime("$TimeFormat",($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst));
  return($metardate,$metartime);
}
($metardate,$metartime)=&CreateTimes($rtime);
sub ProcessValidity{
  my($valid)=shift(@_);
  (my($vt1),my($vt2),my($vt3),my($vt4),my($vt5),my($vt6)) = split (//,$valid);
  my($validendday)='';
  my($validstartday)="$vt1$vt2";
  my($validstarthour)="$vt3$vt4";
  my($validendhour)="$vt5$vt6";
  if (strtod($validendhour)<=strtod($validstarthour)){
    @tm = localtime(time + (24*60*60));
    $validendday=sprintf("%02d\n",$tm[3]); 
  }else{
    $validendday=$validstartday;
  }
  my($validmonth)=strftime("%m",gmtime);
  my($validyear)=strftime("%Y",gmtime);
  return($validstarthour,$validendhour,$validstartday,$validendday,$validmonth,$validyear);
}

if (!$press){ 		$press="$dicstr[45]"	}
if (!$speed){ 		$speed="$dicstr[45]"	}
if (!$visib){ 		$visib="$dicstr[45]"	}
if (!$temp_air){ 	$temp_air="$dicstr[45]"	}
if (!$temp_wch){ 	$temp_wch="$temp_air"	}
if (!$temp_dew){ 	$temp_dew="$dicstr[45]"	}
if (!$visib){ 		$visib="$dicstr[45]"	}
if (!$humid){ 		$humid="$dicstr[45]"	}
if (!$pic){ 		$pic="blank.$ImageFormat"	}
if ($showunits eq 'Y'){
  if ($units eq 'M'){
    $ICAO_StationElevation .=" $dicstr[21]";
    $ICAO_AirElevation .= " $dicstr[21]";
  }else{
    $ICAO_StationElevation .= " $dicstr[22]";
    $ICAO_AirElevation .= " $dicstr[22]";
  }
  $press_in .= " $dicstr[19]";
  $press .= " $dicstr[20]";
  $temp_air_f .= " $dicstr[18]";
  $temp_air .= " $dicstr[17]";
  $temp_wch_f .= " $dicstr[18]";
  $temp_wch .= " $dicstr[17]";
  $temp_dew_f .= " $dicstr[18]";
  $temp_dew .= " $dicstr[17]";
  $humid .= " $dicstr[23]";
}

  $tempdata=$tafdata;
  $i=0;
  # sequence of mornings, afternoons etc.
  local @forecastdaytime = ($dicstr[120], $dicstr[121], $dicstr[122], $dicstr[123]);
  if ($validstarthour<24){$tdindex=2;}
  if ($validstarthour<18){$tdindex=1;}
  if ($validstarthour<12){$tdindex=0;}
  if ($validstarthour<6){$tdindex=3;}
  for ($i = 0; $i < 4; $i++){
    $taftod[$i]="$forecastdaytime[-5+$i+$tdindex+1]";
  }
  @pos = split(/ /,$tempdata);
  foreach $_ (@pos){
    if (/BECMG|TEMPO|RMK/){
      $remember=$_;
    }
    elsif (/^(\d{4})/){
      if ($remember){
        @taftime = split (//,$_);
        ($n1,$n2,$n3,$n4)=@taftime;
        $ftime="$n1$n2";
        $stime="$n3$n4";
        if (($ftime>=18 && $ftime<24) || ($stime>=18 && $stime<24)){$tafforecast[3]=join(" ",$tafforecast[3],"$remember $_");}
        if (($ftime>=12 && $ftime<18) || ($stime>=12 && $stime<18)){$tafforecast[2]=join(" ",$tafforecast[2],"$remember $_");}
        if (($ftime>=6 && $ftime<12) || ($stime>=6 && $stime<12)){$tafforecast[1]=join(" ",$tafforecast[1],"$remember $_");}
        if (($ftime>=0 && $ftime<6) || ($stime>=0 && $stime<6)){$tafforecast[0]=join(" ",$tafforecast[0],"$remember $_");}
        $remember='';
      }else{
        if (($ftime>=18 && $ftime<24) || ($stime>=18 && $stime<24)){$tafforecast[3]=join(" ",$tafforecast[3],"$_");}
        if (($ftime>=12 && $ftime<18) || ($stime>=12 && $stime<18)){$tafforecast[2]=join(" ",$tafforecast[2],"$_");}
        if (($ftime>=6 && $ftime<12) || ($stime>=6 && $stime<12)){$tafforecast[1]=join(" ",$tafforecast[1],"$_");}
        if (($ftime>=0 && $ftime<6) || ($stime>=0 && $stime<6)){$tafforecast[0]=join(" ",$tafforecast[0],"$_");}
      }
    }else{
      if ((($ftime>=18 && $ftime<24) || ($stime>=18 && $stime<24)) && ($_ ne '')){$tafforecast[3]=join(" ",$tafforecast[3],"$_");}
      if ((($ftime>=12 && $ftime<18) || ($stime>=12 && $stime<18)) && ($_ ne '')){$tafforecast[2]=join(" ",$tafforecast[2],"$_");}
      if ((($ftime>=6 && $ftime<12) || ($stime>=6 && $stime<12)) && ($_ ne '')){$tafforecast[1]=join(" ",$tafforecast[1],"$_");}
      if ((($ftime>=0 && $ftime<6) || ($stime>=0 && $stime<6)) && ($_ ne '')){$tafforecast[0]=join(" ",$tafforecast[0],"$_");}
    }
  }
  for ($i = 0; $i < 4; $i++){
    $forewind1='';$forevisib='';@forephenom='';@foreclouds='';$forewind2='';$proba='';
    @pos = split(/ /,$tafforecast[$i]);
    foreach $_ (@pos){
      if (/(..)MPS|(..)KT/)			{		$forewind1 = $_;}
      elsif (/^(\d{6})/)			{		$valid = $_;	}
      elsif (/^(\d{4})|(.)SM|P(.)SM|CAVOK/)	{		$forevisib = $_;}
      elsif (/PROB/)				{		$proba .= $_;}
      elsif (/NIL|DR|MI|FZ|BL|SH|BC|TS|FC|DS|DU|SA|SS|SQ|VA|SN|PY|FU|GR|GS|RA|DZ|BR|SG|IC|PE|FG|HZ|UP|LE/){  push @forephenom, $_;}#if (join(//,@forephenom)!~/$_/) {
      elsif (/FEW|SCT|BKN|OVC|AC|AS|CC|CI|CS|FC|FS|NS|SC|ST/){	if (join(//,@foreclouds)!~/$_/) {push @foreclouds, $_;}}
      elsif (/^(\d{3})V(\d{3})/)		{		$forewind2 = $_;}
    }
    ($validstarthour,$validendhour,$validstartday,$validendday,$validmonth,$validyear)=&ProcessValidity($valid);
    if ($foreclouds[1] =~m/(FEW|SCT)/){
      @foreclouds=&ProcessClouds(@foreclouds);
      $foreclouds=join(//,@foreclouds);
      $foreclouds=~s/\n//g;
      $spokenforecast[$i].=" $dicstr[101] ($foreclouds) ";
    }
    elsif ($foreclouds[1] =~m/(BKN|OVC|TCU|TVC)/){
      @foreclouds=&ProcessClouds(@foreclouds);
      $foreclouds=join(//,@foreclouds);
      $foreclouds=~s/\n//g;
      $spokenforecast[$i].=" $dicstr[102] ($foreclouds) ";
    }
    elsif ($foreclouds[1] =~m/(SKC|CLR|CAVOK|9999)/ || $foreclouds[1] eq ''){
      $spokenforecast[$i].=" $dicstr[99] ";
    }else{
      $spokenforecast[$i].=" $dicstr[99] ";
    }
    #if ($proba ne ''){
    #      $spokenforecast[$i].=" with a probability of 30% ";
    #}
    if ($forephenom >0){  
      @forephenom=&ProcessPhenom(@forephenom);
      $forephenom=join("\n",@forephenom);
      $forephenom=~s/\n//g;
      $spokenforecast[$i].="$dicstr[103] ".lc "$forephenom ";
    }
    ($dummy,$forewind1,$forewind2,$forespeed,$forespeedwind,$forespeed_gusts,$forewdir,$forewdir_deg,$forew9,$foremps,$foretemp_wch,$dummy)=&ProcessWinds($forewind1,,);
    if ($forewind1 ne ''){
      if ($forespeed eq '0'){
        $spokenforecast[$i].=" $dicstr[112] ";
      }
      elsif ($forewdir eq ''){
        $spokenforecast[$i].="  $dicstr[103] $dicstr[104] $dicstr[106] $forespeed $forew9 $forespeed_gusts";
      }else{
        $spokenforecast[$i].="  $dicstr[103] $dicstr[104] $dicstr[105] $forewdir$forewind2 $dicstr[106] $forespeed $forew9 $forespeed_gusts";
      }
    }
    elsif($wind1 ne ''){
      if ($wdir eq ''){
        $spokenforecast[$i].="  $dicstr[103] $dicstr[104] $dicstr[106] $speed $w9 $speed_gusts";
      }else{
        $spokenforecast[$i].="  $dicstr[103] $dicstr[104] $dicstr[105] $wdir $windvarb $dicstr[106] $speed $w9 $speed_gusts";
      }
    }
    $spokenforecast[$i]=ucfirst($spokenforecast[$i]);
    $spokenforecast[$i]=~ s/\s*$//;
    $spokenforecast[$i].=".";
  }

( $MoonPhase,$MoonIllum,$MoonAge,$MoonDist,$MoonAng,$SunDist,$SunAng ) = phase();
$MoonPic=int(($MoonPhase*30));
$MoonPic="moon$MoonPic.$ImageFormat";
@phases = phasehunt();
$MoonPhase1=strftime("$DateFormat",localtime($phases[0]));
$MoonPhase2=strftime("$DateFormat",localtime($phases[1]));
$MoonPhase3=strftime("$DateFormat",localtime($phases[2]));
$MoonPhase4=strftime("$DateFormat",localtime($phases[3]));
$MoonPhase5=strftime("$DateFormat",localtime($phases[4]));
$MoonPhase1_Time=strftime("$TimeFormat",localtime($phases[0]));
$MoonPhase2_Time=strftime("$TimeFormat",localtime($phases[1]));
$MoonPhase3_Time=strftime("$TimeFormat",localtime($phases[2]));
$MoonPhase4_Time=strftime("$TimeFormat",localtime($phases[3]));
$MoonPhase5_Time=strftime("$TimeFormat",localtime($phases[4]));
$longitude=$ICAO_StationLongitude;
$latitude=$ICAO_StationLatitude;
$longitude=~s/$dicstr[88]/,/g;
$latitude=~s/$dicstr[88]/,/g;
$longitude=~s/$dicstr[32]//;
$latitude=~s/$dicstr[28]//;
$longidude=+$longitude;
$latidude=abs($latitude);
$latitude=46.44;
if ($longitude=~s/$dicstr[40]//){
  $longitude=-$longitude;
}
if ($latitude=~s/$dicstr[36]//){
  $latitude=-$latitude;
}
@ltime = localtime;
($sunrise, $sunset) = sunrise( strftime("%Y",gmtime), strftime("%m",gmtime), strftime("%d",gmtime), $longitude, $latitude, $TimeOffset, $ltime[8] );
my @forecast = (['0', '0', '0','0','0'],['0', '0', '0','0','0'],['0', '0', '0','0','0'],['0', '0', '0','0','0'],['0', '0', '0','0','0'],['0', '0', '0','0','0'] ); 
#----
        @lines = split("\n",$myltf);
      ($forecast[0]->[0],$forecast[0]->[1],$forecast[0]->[2],$forecast[0]->[3],$forecast[0]->[4],$forecast[0]->[5])=($lines[0],"",$lines[1],$lines[2],$lines[3],$lines[4]);
      ($forecast[1]->[0],$forecast[1]->[1],$forecast[1]->[2],$forecast[1]->[3],$forecast[1]->[4],$forecast[1]->[5])=($lines[5],"",$lines[6],$lines[7],$lines[8],$lines[9]);
      ($forecast[2]->[0],$forecast[2]->[1],$forecast[2]->[2],$forecast[2]->[3],$forecast[2]->[4],$forecast[2]->[5])=($lines[10],"",$lines[12],$lines[14],$lines[16],$lines[18]);
      ($forecast[3]->[0],$forecast[3]->[1],$forecast[3]->[2],$forecast[3]->[3],$forecast[3]->[4],$forecast[3]->[5])=($lines[11],"",$lines[13],$lines[15],$lines[17],$lines[19]);
      
      for ($i = 0; $i <= 5; $i++) {
       for ($j = 0; $j <= 3; $j++) {
        $forecast[$j]->[$i] =~ s/<.+?>//g; 
        $forecast[$j]->[$i] =~ s/\|//g; 
        $forecast[$j]->[$i] =~ s/&deg;F//g;
        $forecast[$j]->[$i] =~ s/&deg;//g;
        $forecast[$j]->[$i] =~ s/High //g;
        $forecast[$j]->[$i] =~ s/Low //g;
        $forecast[$j]->[$i] =~ s/Almanac//g;
        $forecast[$j]->[$i] =~ s/Detail//g;
        $forecast[$j]->[$i] =~ s/    //g;
        if ($j eq 0){
          $forecast[$j]->[$i]=~s/Mon/$dicstr[125]/e;
          $forecast[$j]->[$i]=~s/Tue/$dicstr[126]/g;
          $forecast[$j]->[$i]=~s/Wed/$dicstr[127]/g;
          $forecast[$j]->[$i]=~s/Thu/$dicstr[128]/g;
          $forecast[$j]->[$i]=~s/Fri/$dicstr[129]/g;
          $forecast[$j]->[$i]=~s/Sat/$dicstr[130]/g;
          $forecast[$j]->[$i]=~s/Sun/$dicstr[131]/g;
          $forecast[$j]->[$i]=~s/night/$dicstr[132]/g;
        }
        if (($j eq 2)||($j eq 3)){
        $forecast[$j]->[$i]=sprintf("%.0f",($forecast[$j]->[$i] - 32.0)/ 1.80);
          if ($units eq 'S'){
            if ($forecast[$j]->[$i] ne ''){$forecast[$j]->[$i]=sprintf("%.0f",1.80 * $forecast[$j]->[$i] + 32.0);}
            if ($showunits eq 'Y'){
              if ($forecast[$j]->[$i] ne ''){$forecast[$j]->[$i].="$dicstr[18]";}
            }
          }else{
            if ($showunits eq 'Y'){
              if ($forecast[$j]->[$i] ne ''){$forecast[$j]->[$i].="$dicstr[17]";}
            }
          }
        }
        if ($j eq 1){
          $forecastpic="blank.$ImageFormat";
          $fc=lc($forecast[$j]->[$i]);
          if ($fc=~m/cloud/)
          { 
            $forecastpic="cloudy.$ImageFormat";
            if ($fc=~m/periods|few|scattered/)
            { 
              $forecastpic="ptcloudy.$ImageFormat";
            }
            if ($fc=~/main/)
            {
              $forecastpic="mscloudy.$ImageFormat";
            }
          }
          if ($fc=~m/shower/)
          {
            if ($fc=~m/few/)
            {
              $forecastpic="scshowers.$ImageFormat";
            }else{
              $forecastpic="showers.$ImageFormat";
            }
          }
          if ($fc=~m/sunny/)
          {
             $forecastpic="sun.$ImageFormat";
             if ($fc=~m/mainly|period/)
             {
               $forecastpic="ptcloudy.$ImageFormat";
             }
          }
          if ($fc=~m/clear/)
          {
             $forecastpic="sun.$ImageFormat";
             if ($fc=~m/mainly|period/)
             {
                $forecastpic="ptcloudy.$ImageFormat";
             }
          }
          if ($fc=~m/overcast/)
          {
            $forecastpic="cloudy.$ImageFormat";
          }
          if ($fc=~m/rain/)
          {
             $forecastpic="rain.$ImageFormat";
          }
          if ($fc=~m/storm/)
          {
             $forecastpic="thunderstorm.$ImageFormat";
          }
          $forecast[4]->[$i]="$forecastpic";
          
          $forecast[$j]->[$i]=~s/(A|a) / $dicstr[156] /g;
          $forecast[$j]->[$i]=~s/(O|o)f/$dicstr[154]/g;
          $forecast[$j]->[$i]=~s/(P|p)artly Cloudy/$dicstr[101]/g;
          $forecast[$j]->[$i]=~s/(C|c)loudy/$dicstr[140]/g;
          $forecast[$j]->[$i]=~s/(O|o)vercast/$dicstr[165]/g;
          $forecast[$j]->[$i]=~s/(S|s)unny/$dicstr[141]/g;
          $forecast[$j]->[$i]=~s/(S|s)cattered Clouds/$dicstr[101]/g;
          $forecast[$j]->[$i]=~s/(C|c)loudiness/$dicstr[142]/g;
          $forecast[$j]->[$i]=~s/(P|p)eriods/$dicstr[143]/g;
          $forecast[$j]->[$i]=~s/(V|v)ariable/$dicstr[144]/g;
          $forecast[$j]->[$i]=~s/(C|c)learing/$dicstr[152]/g;
          $forecast[$j]->[$i]=~s/(C|c)lear/$dicstr[145]/g;
          $forecast[$j]->[$i]=~s/(S|s)howers/$dicstr[146]/g;
          $forecast[$j]->[$i]=~s/(F|f)ew/$dicstr[147]/g;
          $forecast[$j]->[$i]=~s/(M|m)ainly/$dicstr[148]/g;
          $forecast[$j]->[$i]=~s/(M|m)orning/$dicstr[149]/g;
          $forecast[$j]->[$i]=~s/(C|c)loud(s)/$dicstr[150]/g;
          $forecast[$j]->[$i]=~s/(I|i)ncreasing/$dicstr[151]/g;
          $forecast[$j]->[$i]=~s/(C|c)hance/$dicstr[153]/g;
          $forecast[$j]->[$i]=~s/(F|f)lurries/$dicstr[155]/g;
          $forecast[$j]->[$i]=~s/(M|m)ix/$dicstr[157]/g;
          $forecast[$j]->[$i]=~s/(S|s)un/$dicstr[158]/g;
          $forecast[$j]->[$i]=~s/ (A|a)nd / $dicstr[159] /g;
          $forecast[$j]->[$i]=~s/(L|l)ight/$dicstr[160]/g;
          $forecast[$j]->[$i]=~s/(H|h)eavy/$dicstr[161]/g;
          $forecast[$j]->[$i]=~s/(S|s)now/$dicstr[162]/g;
          $forecast[$j]->[$i]=~s/(R|r)ain/$dicstr[163]/g;
          $forecast[$j]->[$i]=~s/(H|h)ail/$dicstr[164]/g;
          $forecast[$j]->[$i]=~s/(T|t)-storms/$dicstr[60]/g;
          $forecast[$j]->[$i]=~ s/([A-Za-z])([A-Za-z]+)/\U$1\E\L$2\E/g;
        }
  }
}

$ICAO_StationLongitude=~ s/^0+//g;
$ICAO_StationLatitude=~ s/^0+//g;
$ICAO_AirLongitude=~ s/^0+//g;
$ICAO_AirLatitude=~ s/^0+//g;
$resultPage.="@templatePage";#if ($imager eq ''){$resultPage="$wind_dec_speed$resultPage";}
if ($nodata eq 1){
  $resultPage=~s/<!--\s?\/?START_CURRENT[^>]*>.*<!--\s?\/?END_CURRENT[^>]*>/@templateNoCURRENTPage/gs;
}
if ($notafdata eq 1){
  $resultPage=~s/<!--\s?\/?START_TAF[^>]*>.*<!--\s?\/?END_TAF[^>]*>/@templateNoTAFPage/gs;
}
if ($noltfdata eq 1){
  $resultPage=~s/<!--\s?\/?START_5DAY[^>]*>.*<!--\s?\/?END_5DAY[^>]*>/@templateNoLTFPage/gs;
}
if ($imager eq ''){
  if ($ImageURL ne ''){
    $fulllocation.="$ImageURL/";
  }
  if ($ImageSet ne ''){
    $fulllocation.="$ImageSet/";
  }
  $MoonPic="$fulllocation$MoonPic";
  $pic="$fulllocation$pic";
  for ($i = 0; $i <= 5; $i++) {
    $forecast[4]->[$i]="$fulllocation$forecast[4]->[$i]";
  }
}else{
  if ($ImageDir ne ''){
    $fulllocation.="$ImageDir/";
  }
  if ($ImageSet ne ''){
    $fulllocation.="$ImageSet/";
  }
  $MoonPic="$fulllocation$MoonPic";
  $pic="$fulllocation$pic";
  for ($i = 0; $i <= 5; $i++) {
    $forecast[4]->[$i]="$fulllocation$forecast[4]->[$i]";
  }
}

$clouds=join(//,@clouds);
$clouds=~s/\n//g;
$phenom=join(//,@phenom);
$phenom=~s/\n//g;

$resultPage=~s/<!-- METAR_ICAO -->/$cccc/g;
$resultPage=~s/<!-- METAR_PHENOM -->/$phenom/g;
$resultPage=~s/<!-- METAR_WIND_SPEED -->/$speed $w9 $speed_gusts/g;
$resultPage=~s/<!-- METAR_WIND_SPEED_KT -->/$speed_knots/g;
$resultPage=~s/<!-- METAR_WIND_SPEED_KM -->/$speed_km/g;
$resultPage=~s/<!-- METAR_WIND_SPEED_BEAUFORT -->/$speed_beaufort/g;
$resultPage=~s/<!-- METAR_WIND_DIR -->/$wdir/g;
$resultPage=~s/<!-- METAR_WIND_VAR -->/$windvarb/g;
$resultPage=~s/<!-- METAR_WIND_DIR_DEG -->/$wdir_deg/g;
$resultPage=~s/<!-- METAR_WIND_ALL -->/$wind_all/g;
$resultPage=~s/<!-- METAR_PRES_IN -->/$press_in/g;
$resultPage=~s/<!-- METAR_PRES_PA -->/$press/g;
$resultPage=~s/<!-- METAR_CLOUDS -->/$clouds/g;
$resultPage=~s/<!-- METAR_TIME -->/$metartime/g;
$resultPage=~s/<!-- METAR_DATE -->/$metardate/g;
$resultPage=~s/<!-- METAR_CURRENT_TIME -->/$currenttime/g;
$resultPage=~s/<!-- METAR_CURRENT_DATE -->/$currentdate/g;
$resultPage=~s/<!-- METAR_VIS -->/$visib/g;
$resultPage=~s/<!-- METAR_TEMP_F -->/$temp_air_f/g;
$resultPage=~s/<!-- METAR_TEMP_C -->/$temp_air/g;
$resultPage=~s/<!-- METAR_WCH_F -->/$temp_wch_f/g;
$resultPage=~s/<!-- METAR_WCH_C -->/$temp_wch/g;
$resultPage=~s/<!-- METAR_DEW_F -->/$temp_dew_f/g;
$resultPage=~s/<!-- METAR_DEW_C -->/$temp_dew/g;
$resultPage=~s/<!-- METAR_HUMI -->/$humid/g;
$resultPage=~s/<!-- METAR_PIC -->/$pic/g;
$resultPage=~s/<!-- METAR_PLACE -->/$ICAO_Place/g;
$resultPage=~s/<!-- METAR_CITY -->/$ICAO_City/g;
$resultPage=~s/<!-- METAR_COUNTRY -->/$ICAO_Country/g;
$resultPage=~s/<!-- METAR_STLONG -->/$ICAO_StationLongitude/g;
$resultPage=~s/<!-- METAR_STLAT -->/$ICAO_StationLatitude/g;
$resultPage=~s/<!-- METAR_AIRLONG -->/$ICAO_AirLongitude/g;
$resultPage=~s/<!-- METAR_AIRLAT -->/$ICAO_AirLatitude/g;
$resultPage=~s/<!-- METAR_STELEV -->/$ICAO_StationElevation/g;
$resultPage=~s/<!-- METAR_AIRELEV -->/$ICAO_AirElevation/g;
$resultPage=~s/<!-- METAR_COLOR -->/$colorc/g;
$resultPage=~s/<!-- METAR_COLORC -->/$colorcode/g;
$resultPage=~s/<!-- TAF_VALID_STARTDAY -->/$validstartday/g;
$resultPage=~s/<!-- TAF_VALID_ENDDAY -->/$validendday/g;
$resultPage=~s/<!-- TAF_VALID_STARTHOUR -->/$validstarthour/g;
$resultPage=~s/<!-- TAF_VALID_ENDHOUR -->/$validendhour/g;
$resultPage=~s/<!-- TAF_VALID_MONTH -->/$validmonth/g;
$resultPage=~s/<!-- TAF_VALID_YEAR -->/$validyear/g;
$resultPage=~s/<!-- TAF_REMARK_COUNT -->/$tafremarks/g;
$resultPage=~s/<!-- TAF_TOD_1 -->/$taftod[0]/g;
$resultPage=~s/<!-- TAF_TOD_2 -->/$taftod[1]/g;
$resultPage=~s/<!-- TAF_TOD_3 -->/$taftod[2]/g;
$resultPage=~s/<!-- TAF_TOD_4 -->/$taftod[3]/g;
$resultPage=~s/<!-- TAF_1 -->/$spokenforecast[0]/g;
$resultPage=~s/<!-- TAF_2 -->/$spokenforecast[1]/g;
$resultPage=~s/<!-- TAF_3 -->/$spokenforecast[2]/g;
$resultPage=~s/<!-- TAF_4 -->/$spokenforecast[3]/g;
$resultPage=~s/<!-- METAR_IMAGE_URL -->/$ImageURL/g;
$resultPage=~s/<!-- METAR_RAW -->/$cccc $line1/g;
$resultPage=~s/<!-- TAF_RAW -->/$cccc $linetaf1/g;
# Below is new since version 3.2
$resultPage=~s/<!-- METAR_MOONPHASE1 -->/$MoonPhase1/g;
$resultPage=~s/<!-- METAR_MOONPHASE2 -->/$MoonPhase2/g;
$resultPage=~s/<!-- METAR_MOONPHASE3 -->/$MoonPhase3/g;
$resultPage=~s/<!-- METAR_MOONPHASE4 -->/$MoonPhase4/g;
$resultPage=~s/<!-- METAR_MOONPHASE5 -->/$MoonPhase5/g;
$resultPage=~s/<!-- METAR_MOONPHASE1_TIME -->/$MoonPhase1_Time/g;
$resultPage=~s/<!-- METAR_MOONPHASE2_TIME -->/$MoonPhase2_Time/g;
$resultPage=~s/<!-- METAR_MOONPHASE3_TIME -->/$MoonPhase3_Time/g;
$resultPage=~s/<!-- METAR_MOONPHASE4_TIME -->/$MoonPhase4_Time/g;
$resultPage=~s/<!-- METAR_MOONPHASE5_TIME -->/$MoonPhase5_Time/g;
$resultPage=~s/<!-- METAR_MOONPHASE_PIC -->/$MoonPic/g;
$resultPage=~s/<!-- METAR_SUNRISE -->/$sunrise/g;
$resultPage=~s/<!-- METAR_SUNSET -->/$sunset/g;
$resultPage=~s/<!-- METAR_TIME_OFFSET -->/$TimeOffset/g;
# Below has been added as of version 4.0
$resultPage=~s/<!-- FORECAST_1_DAY -->/$forecast[0]->[0]/g;
$resultPage=~s/<!-- FORECAST_1_NIGHT -->/$forecast[0]->[1]/g;
$resultPage=~s/<!-- FORECAST_2_DAY -->/$forecast[0]->[2]/g;
$resultPage=~s/<!-- FORECAST_3_DAY -->/$forecast[0]->[3]/g;
$resultPage=~s/<!-- FORECAST_4_DAY -->/$forecast[0]->[4]/g;
$resultPage=~s/<!-- FORECAST_5_DAY -->/$forecast[0]->[5]/g;
$resultPage=~s/<!-- FORECAST_1_DAY_PIC -->/$forecast[4]->[0]/g;
$resultPage=~s/<!-- FORECAST_1_NIGHT_PIC -->/$forecast[4]->[1]/g;
$resultPage=~s/<!-- FORECAST_2_DAY_PIC -->/$forecast[4]->[2]/g;
$resultPage=~s/<!-- FORECAST_3_DAY_PIC -->/$forecast[4]->[3]/g;
$resultPage=~s/<!-- FORECAST_4_DAY_PIC -->/$forecast[4]->[4]/g;
$resultPage=~s/<!-- FORECAST_5_DAY_PIC -->/$forecast[4]->[5]/g;
$resultPage=~s/<!-- FORECAST_1_DAY_COND -->/$forecast[1]->[0]/g;
$resultPage=~s/<!-- FORECAST_1_NIGHT_COND -->/$forecast[1]->[1]/g;
$resultPage=~s/<!-- FORECAST_2_DAY_COND -->/$forecast[1]->[2]/g;
$resultPage=~s/<!-- FORECAST_3_DAY_COND -->/$forecast[1]->[3]/g;
$resultPage=~s/<!-- FORECAST_4_DAY_COND -->/$forecast[1]->[4]/g;
$resultPage=~s/<!-- FORECAST_5_DAY_COND -->/$forecast[1]->[5]/g;
$resultPage=~s/<!-- FORECAST_1_DAY_HIGH -->/$forecast[2]->[0]/g;
$resultPage=~s/<!-- FORECAST_1_NIGHT_HIGH -->/$forecast[2]->[1]/g;
$resultPage=~s/<!-- FORECAST_2_DAY_HIGH -->/$forecast[2]->[2]/g;
$resultPage=~s/<!-- FORECAST_3_DAY_HIGH -->/$forecast[2]->[3]/g;
$resultPage=~s/<!-- FORECAST_4_DAY_HIGH -->/$forecast[2]->[4]/g;
$resultPage=~s/<!-- FORECAST_5_DAY_HIGH -->/$forecast[2]->[5]/g;
$resultPage=~s/<!-- FORECAST_1_DAY_LOW -->/$forecast[3]->[0]/g;
$resultPage=~s/<!-- FORECAST_1_NIGHT_LOW -->/$forecast[3]->[1]/g;
$resultPage=~s/<!-- FORECAST_2_DAY_LOW -->/$forecast[3]->[2]/g;
$resultPage=~s/<!-- FORECAST_3_DAY_LOW -->/$forecast[3]->[3]/g;
$resultPage=~s/<!-- FORECAST_4_DAY_LOW -->/$forecast[3]->[4]/g;
$resultPage=~s/<!-- FORECAST_5_DAY_LOW -->/$forecast[3]->[5]/g;

# as of post-release version 4.01
if ($wdirimg eq "NA"){
  $resultPage=~s/<!-- METAR_WIND_DIR_IMG -->/NA.$ImageFormat/g;
}elsif ($wdir_deg =~ m/-/g){
  $resultPage=~s/<!-- METAR_WIND_DIR_IMG -->/variable.$ImageFormat/g;
}else{
  $resultPage=~s/<!-- METAR_WIND_DIR_IMG -->/$wdirimg.$ImageFormat/g;
}
$resultPage=~s/<!-- METAR_QUERYSTR -->/$ENV{QUERY_STRING}/g;
$resultPage=~s/<!-- METAR_CUSTOMQUERYSTR -->/$customquery/g;
#process formulas in template
@mymatches=$resultPage=~m/(\{\{.*\}\})/g;
foreach $mymatch (@mymatches)
{
  $myresult=$mymatch;
  $myresult=~s/[a-zA-Z&deg;%]//g;
  $myresult=~s/\s//g;
  $myresult=~s/(\{|\})//g;
  $myresult=eval("$myresult");
  $mymatch=~s/\*/\\\*/g;
  $mymatch=~s/\+/\\\+/g;
  $mymatch=~s/\(/\\\(/g;
  $mymatch=~s/\)/\\\)/g;
  $resultPage=~s/$mymatch/$myresult/g;
}

# process custom parameters
# for each pair 
for (split /[&;]/, $customquery) { 
my ($k,$v) = split /=/, $_; 
$customtagname=uc $k;
$resultPage=~s/<!-- $customtagname -->/$v/g;
next if $k eq ""; 
} 

if ($imager eq ''){
  print "$resultPage\n";
}

#------------------------------------------------------------------------------#
# LIB END
#------------------------------------------------------------------------------#
if ($imager ne ''){
  if  (eval "require GD") { 
    $imageformat=$imager;
    require("$BaseDir/mimager.lib");
  }else{
    DisplayError("Imager:<BR>The GD module is unavailable. Imager will not work until GD is installed. You can download the GD module from http://www.boutell.com/gd, or install it from within Perl. Consult your Perl user manual.");
  }
}
exit 0;
}
# -----------------------------------------------------------------------------#
# !! IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT  !! #
# -----------------------------------------------------------------------------#
# The following lines display the 'Powered by Metar.pl' line on the end of the #
# Metar/Taf report. Not having paid the required license fee for Metar.pl,     #
# editing these lines will result in a direct violation of the software        # 
# license, which is illegal. Read license.txt included in this distribution    #
# for more information. Be aware that we are very much aware of license        #
# agreement violations, and we will prosecute to the fullest extent of the law.#
# -----------------------------------------------------------------------------#
#
# ------------------------------------------------------------------------------
# (C)2000-2003 Coyote Mediaproductions. All rights reserved.
# ------------------------------------------------------------------------------
