495 lines
19 KiB
PHP
495 lines
19 KiB
PHP
<?
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ALBasic
|
|
//
|
|
// Author: Christian Mähler
|
|
// Version: 9
|
|
// Last update: December 2002
|
|
//
|
|
// Base library for map&guide TCP/IP communication to
|
|
// address locator server and map&guide intranet server
|
|
// Batch Control is not supported (!)
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
class ALBasic
|
|
{
|
|
// common parameter as documented for the public user interface
|
|
|
|
var $BPParaBCPath; // old batch control path
|
|
var $BPParaRequestFileName; // filename of the file to be generated
|
|
var $BPBatchUrl; // URL where to find the file
|
|
var $BPPictureFormat; // format of picture to be generated
|
|
var $BPLogFilePath; // logfile path including filename!!
|
|
var $BPUseTCPIP; // use TCP/IP? should be always true because Batch Control is not supported with this class
|
|
var $BPMaximumFileAge; // maximum time for a file to stay on hard disk (in minutes)
|
|
var $BPStreamDirectory; // directory where to write the maps from the stream
|
|
var $BPMapsByStream; // send map as stream?
|
|
var $BPStreamToDisk; // write stream to hard disk?
|
|
var $BPMapStream; // contains map stream
|
|
var $eATCor; // AnswerType for BFGetParam = 1
|
|
var $eATAns; // AnswerType for BFGetParam = 0
|
|
var $BPALS; // list of all server as string
|
|
var $BPUrlNameMap; // name of map file (URL from docroot with filename)
|
|
var $BPMaxSocketWait; // time to wait for a server socket connect
|
|
var $BPCalcWait; // time to wait for the whole server request to finish including the search for this server
|
|
// this is not yet supported in PHP
|
|
|
|
// constants
|
|
|
|
var $BPStat_PropriError; // 0
|
|
var $BPStat_Error; // 1
|
|
var $BPStat_Success; // 2
|
|
var $BPGeoStat_Select; // 3
|
|
var $BPRouteStat_NoLocFound; // 4
|
|
|
|
// private variables
|
|
|
|
var $BPTCPAnswer; // TCP answer; every row in an array (BPTCPAnswer[ANS][0] == row 1 of server answer)
|
|
var $BPBCAnswer; // Hier steht die BC-Antwort. Jede Zeile in einem Array (BPBCAnswer[COR][0] == Zeile 1 der Zwischendatei)
|
|
var $BPFPTCP; // FileHandle for TCP communication
|
|
var $BPFileCount; // unique number for file to generate
|
|
var $BPRequest; // internal request string (necessary for BFAddParam)
|
|
var $BPALSTCP; // assoc. array with Name, IP, Port and state of the server
|
|
var $BCAnswerList; // contains an associative array with the content of the answer file
|
|
var $BPWINOS; // true if operating system is windows
|
|
var $BPUNIXOS; // true if operating system is UNIX
|
|
var $TCPtemp; // temporary variable for TCP/IP answer from server
|
|
|
|
// the following internal variables define the service to request at server side
|
|
// defined by ACTION or SUBACTION in request
|
|
|
|
var $BPGeoServiceNum;
|
|
var $NR_MAPREQUEST; // 2
|
|
var $NR_GEO; // 7
|
|
var $NR_ROUTEREQUEST_ROUTEID; // 30
|
|
var $NR_ROUTEREQUEST; // 3
|
|
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ALBasic
|
|
// constructor for class ALBasic
|
|
|
|
function ALBasic()
|
|
{
|
|
set_time_limit(60); // set maximum execution time for PHP script
|
|
$this->BPMapsByStream=false; // maps are coming as stream by default
|
|
$this->BPLogFilePath=""; // set LogFilePath
|
|
$this->eATCor = 1; // const for correction part of server answer
|
|
$this->eATAns = 0; // const for answer part of server answer
|
|
$this->BPMaxSocketWait=60; // wait 60 seconds per server for a socket connect
|
|
$this->BPMaximumFileAge=10; // leave the generated maps 10 seconds as a maximum on hard disk
|
|
$this->BPStat_PropriError= 0; // unknown error
|
|
$this->BPStat_Error = 1; // known error
|
|
$this->BPStat_Success = 2; // success (one hit - geocoding)
|
|
$this->BPGeoStat_Select = 3; // success (multiple hits - geocoding)
|
|
$this->BPRouteStat_Select= 3; // should never happen (old value!)
|
|
$this->BPRouteStat_NoLocFound = 4; // should never happen (old value!)
|
|
$this->BPWINOS = false; // not used at the moment
|
|
$this->BPUNIXOS = false; // not used at the moment
|
|
$this->BFSetFileCount(); // get file count
|
|
$this->BPStreamToDisk=true;
|
|
// BPUrlNameMap = URL to map if correct parameters were passed
|
|
$this->BPUrlNameMap = $this->BPParaBCUrl . $this->BPParaRequestFileName . $this->BPFileCount; // . "." . $this->BPPictureFormat;
|
|
|
|
$this->Log_to_file("ALBasic.ALBasic: Passed successfully.");
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// BFGetTCPAnsLength
|
|
// Gets the length from the response stream in byte. The length is defined
|
|
// as a 12 byte string with leading 0s. E.g.: #0000000111#, answer is 111
|
|
// byte long
|
|
|
|
function BFGetTCPAnsLength($fp)
|
|
{
|
|
if (!$fp || feof($fp)) return 0;
|
|
$bufferArray = explode("#",fread($fp,12));
|
|
return ((int)$bufferArray[1])-11;
|
|
$this->Log_to_file("ALBasic.BFGetTCPAnsLength: Passed Succesfully");
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// BFReadALSAnswer
|
|
// Reads complete answer from TCP/IP stream and splits stream into
|
|
// COR (correction) and ANS (answer) parts. Every line is read into
|
|
// a single associative array
|
|
|
|
function BFReadALSAnswer($servicenum)
|
|
{
|
|
if($this->TCPtemp=="") return false;
|
|
|
|
// read complete answer stream into arrays
|
|
if ($servicenum==$this->NR_NEXTREQUEST || $servicenum==$this->NR_ROUTEREQUEST || $servicenum==$this->NR_GEOREQUEST)
|
|
{
|
|
$this->BPTCPAnswer["COR"] = explode("^", $this->TCPtemp[2]);
|
|
$this->BPTCPAnswer["ANS"] = explode("^", $this->TCPtemp[6]);
|
|
}
|
|
else
|
|
$this->BPTCPAnswer["ANS"] = explode("^", $this->TCPtemp[2]);
|
|
|
|
// read every single line of answer section ANS into an assoc. array
|
|
for ($i = 0; $i < count($this->BPTCPAnswer["ANS"])-1 ;$i++)
|
|
{
|
|
$tmp = explode("~", $this->BPTCPAnswer["ANS"][$i]);
|
|
$this->BCAnswerList["ANS"][$tmp[0]][$tmp[1]]=$tmp[2];
|
|
}
|
|
|
|
// read every single line of correction section COR into an assoc. array
|
|
if(is_array($this->BPTCPAnswer["COR"]))
|
|
for ($i = 0; $i < count($this->BPTCPAnswer["COR"])-1 ;$i++)
|
|
{
|
|
$tmp = explode("~", $this->BPTCPAnswer["COR"][$i]);
|
|
$this->BCAnswerList["COR"][$tmp[0]][$tmp[1]]=$tmp[2];
|
|
}
|
|
|
|
// read maps from stream if applicable
|
|
if($this->BPMapsByStream)
|
|
{
|
|
//[MAPS]
|
|
//MAPSTREAMS=<Picture name>,<Size>|<Picture name>,<Size>|<Picture name>,<Size>|...
|
|
$maps=explode("|",$this->BFGetParam($this->eATAns,"MAPS","MAPSTREAMS",""));
|
|
|
|
if(count($maps)>0)
|
|
{
|
|
for($i=0;$i<count($maps);$i++)
|
|
{
|
|
// read one dummy byte between ASCII stream and binary stream
|
|
// this strange behavior is necessary
|
|
if($i==0) $temp=fread($this->BPFPTCP,1);
|
|
|
|
// read map from stream
|
|
$mapstream=explode(",",$maps[$i]);
|
|
$temp = fread($this->BPFPTCP, $mapstream[1]);
|
|
|
|
$this->BPMapStream=array($i => $temp);
|
|
|
|
// write map to file
|
|
if($this->BPStreamToDisk && $this->BPStreamDirectory!="")
|
|
{
|
|
$fp=@fopen($this->BPStreamDirectory."/".$mapstream[0],"wb");
|
|
if($fp)
|
|
{
|
|
fwrite($fp,$temp);
|
|
fclose($fp);
|
|
}
|
|
else
|
|
$this->Log_to_file("ALBasic.BFReadALSAnswer: Error while writing map to hard disk: MapFile ".$this->BPStreamDirectory."/".$mapstream[0]);
|
|
}
|
|
}
|
|
|
|
srand ((double)microtime()*1000000);
|
|
if(rand(0,100)%2 == 0) // deletion is performed
|
|
$this->BFDeleteOldFiles();
|
|
}
|
|
}
|
|
|
|
|
|
$this->Log_to_file("ALBasic.BFReadALSAnswer: Passed Succesfully");
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// BFSetFileCount
|
|
// Get single name for the naming of the generated files. Has to be
|
|
// explicitly used by the user. This file count is not automatically
|
|
// added to a file name!
|
|
|
|
function BFSetFileCount()
|
|
{
|
|
$mytime=gettimeofday();
|
|
$this->BPFileCount = $mytime["sec"]."--".$mytime["usec"];
|
|
$this->Log_to_file("ALBasic.BFSetFileCount: Passed Succesfully");
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// BFBuildOrder()
|
|
// assembles request to server according to the content of the associative
|
|
// arrays containing the properties and their values
|
|
|
|
function BFBuildOrder()
|
|
{
|
|
$request="";
|
|
$separator="'^'";
|
|
|
|
// add user defined parameter for variables of ALBasic
|
|
if($this->BPPictureFormat!="")
|
|
$this->BPRequest["CLIENT"]["BPPICTUREFORMAT"]=$this->BPPictureFormat;
|
|
|
|
// build all values concerning SERVER section
|
|
reset($this->BPRequest["SERVER"]);
|
|
while (list($key, $value) = each ($this->BPRequest["SERVER"]))
|
|
$request .= "SERVER~$key~$value" . $separator;
|
|
|
|
// build all values concerning CLIENT section
|
|
reset($this->BPRequest["CLIENT"]);
|
|
while (list($key, $value) = each ($this->BPRequest["CLIENT"]))
|
|
$request .= "CLIENT~$key~$value" . $separator;
|
|
|
|
// build all values concerning special section (login) if applicable
|
|
// it's necesary for the function WRITE_OPTIONS where a section
|
|
// called after the login name is available
|
|
$login=strtoupper($this->BPRequest["CLIENT"]["LOGIN"]);
|
|
if (sizeof($this->BPRequest[$login])>0)
|
|
{
|
|
reset($this->BPRequest[$login]);
|
|
$numo=0;
|
|
while (list($key, $value) = each ($this->BPRequest[$login]))
|
|
{
|
|
$numo++;
|
|
$request .= $login."~OPTION".$numo."~$key^$value".$separator;
|
|
}
|
|
$request .= $login."~NUMOPTIONS~$numo".$separator;
|
|
}
|
|
|
|
// return ready built request
|
|
|
|
$this->Log_to_file("ALBasic.BFBuildOrder: Passed Succesfully: Request: #BAL##FN#".$this->BPParaRequestFileName."#ENDFN#" . $request . "#SEP#" . $separator . "#ENDSEP##ENDBAL#");
|
|
|
|
return "#BAL##FN#".$this->BPParaRequestFileName."#ENDFN#" . $request . "#SEP#" . $separator . "#ENDSEP##ENDBAL#\r\n";
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// BFWriteOrder
|
|
// Opens TCP/IP connection and sends request to server.
|
|
|
|
function BFWriteOrder($request)
|
|
{
|
|
// split list of all available servers
|
|
$serverlist=explode("^",$this->BPALS);
|
|
|
|
// check every server in round robin manner until timeout or connect
|
|
for($x=0;$x<count($serverlist);$x++)
|
|
{
|
|
// get next server from list
|
|
list($this->BPALSTCP["NAME"],$this->BPALSTCP["IP"],$this->BPALSTCP["PORT"],$this->BPALSTCP["ACTIVE"])=explode(",",$serverlist[$x]);
|
|
// if server is set to "active" in server list, try to connect
|
|
if((int)$this->BPALSTCP["ACTIVE"]==1)
|
|
{
|
|
// reset connection
|
|
$this->BPFPTCP = false;
|
|
// connect to IP and port of server
|
|
$this->BPFPTCP = @fsockopen ($this->BPALSTCP["IP"], $this->BPALSTCP["PORT"], &$errno, &$errstr, $this->BPMaxSocketWait);
|
|
|
|
// if connection was enabled, write request
|
|
if ($this->BPFPTCP && !feof($this->BPFPTCP))
|
|
{
|
|
$answerlength=0;
|
|
$starttime=time();
|
|
|
|
while($answerlength<100 && (time()-$starttime<5) && $this->BPFPTCP && !feof($this->BPFPTCP))
|
|
{
|
|
// write request
|
|
@fputs ($this->BPFPTCP,$request);
|
|
$this->Log_to_file("ALBasic.BFWriteOrder: succesful server connect: Server: ".$this->BPALSTCP["IP"].":".$this->BPALSTCP["PORT"]);
|
|
|
|
// get answer length
|
|
$answerlength=$this->BFGetTCPAnsLength($this->BPFPTCP);
|
|
|
|
// #0000000024##DISABLED##ENDDISABLED#
|
|
// #0000000037##BUSY#<Milliseconds_working>~<TreadID>#ENDBUSY#
|
|
// #0000000042##ERROR#<Error description>#ENDERROR#
|
|
$this->TCPtemp="";
|
|
$errno=$answerlength;
|
|
// if answer length is less than 100, we received an error from server
|
|
if($answerlength<100)
|
|
{
|
|
if($answerlength>0)
|
|
$tcptmp=fgets($this->BPFPTCP, $answerlength);
|
|
|
|
if($answerlength==24)
|
|
$this->Log_to_file("ALBasic.BFWriteOrder: Server is disabled: Server: ".$this->BPALSTCP["IP"].":".$this->BPALSTCP["PORT"]." server answer: ".$tcptmp);
|
|
else
|
|
if($answerlength>0)
|
|
$this->Log_to_file("ALBasic.BFWriteOrder: Server error: Server: ".$this->BPALSTCP["IP"].":".$this->BPALSTCP["PORT"]." server answer: ".$tcptmp);
|
|
else
|
|
$this->Log_to_file("ALBasic.BFWriteOrder: Server error: Server: ".$this->BPALSTCP["IP"].":".$this->BPALSTCP["PORT"]." server answer: none");
|
|
|
|
fclose($this->BPFPTCP);
|
|
usleep(300); // dos not work with windows
|
|
$this->BPFPTCP = @fsockopen ($this->BPALSTCP["IP"], $this->BPALSTCP["PORT"], &$errno, &$errstr, $this->BPMaxSocketWait);
|
|
}
|
|
else
|
|
{
|
|
$this->TCPtemp = explode("#", fgets($this->BPFPTCP, $answerlength));
|
|
return $answerlength;
|
|
break;
|
|
}
|
|
|
|
} // try to send request to one server (end while)
|
|
}
|
|
else
|
|
{
|
|
$this->Log_to_file("ALBasic.BFWriteOrder: Error while writing to socket: Server: ".$this->BPALSTCP["IP"].":".$this->BPALSTCP["PORT"]);
|
|
} // end server connect
|
|
} // server active
|
|
} // end for
|
|
|
|
if($this->TCPtemp=='')
|
|
$this->Log_to_file("ALBasic.BFWriteOrder: Passed without server connect");
|
|
else
|
|
$this->Log_to_file("ALBasic.BFWriteOrder: Passed Succesfully");
|
|
|
|
return $errno;
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// BFCheckParam
|
|
// Check whether all necessary parameters are available dependent on
|
|
// the service requested by the server.
|
|
// returns clear text error message
|
|
|
|
function BFCheckParam($servicenum)
|
|
{
|
|
$err_msg='';
|
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// common parameters
|
|
|
|
if ($this->BPALS == "")
|
|
$err_msg = "Warning: No server defined!";
|
|
elseif (($servicenum==$this->NR_MAPREQUEST || $servicenum==$this->NR_ROUTINGREQUEST) && $this->BPParaRequestFileName == "")
|
|
$err_msg = "Warning: No name for file to generate!";
|
|
|
|
$this->Log_to_file("ALBasic.BFCheckParam: Regular error message: ".$err_msg);
|
|
|
|
if($err_msg!='')
|
|
{
|
|
if ($servicenum == $this->NR_GEOREQUEST)
|
|
$this->GeoResponse = $err_msg;
|
|
if ($servicenum == $this->NR_MAPREQUEST)
|
|
$this->MapResponse = $err_msg;
|
|
if ($servicenum == $this->NR_ROUTINGREQUEST)
|
|
$this->RouteResponse = $err_msg;
|
|
return $this->BPStat_Error;
|
|
}
|
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// error messages for geocoding service
|
|
|
|
if ($servicenum == $this->NR_GEOREQUEST)
|
|
{
|
|
if ($this->ParaRequestType == "")
|
|
{
|
|
if ($servicenum == $this->NR_GEOREQUEST)
|
|
$this->GeoResponse = "Warning: Parameter ParaRequestType not defined!";
|
|
$this->Log_to_file("ALBasic.BFCheckParam: Regular error message (geocoding): ".$this->GeoResponse);
|
|
return $this->BPStat_Error;
|
|
}
|
|
}
|
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// error messages for mapping service
|
|
|
|
if ($servicenum == $this->NR_MAPREQUEST)
|
|
{
|
|
if ($this->MapRequestRect == "" and $this->MapObjectList == "" and $this->BPRequest[CLIENT][LOGICALRECT]=="" and $this->BPRequest[CLIENT][CST1] =="")
|
|
{
|
|
$this->MapResponse = "Warning: No bounding rect and no objects defined!";
|
|
$this->Log_to_file("ALBasic.BFCheckParam: Regular error message (geocoding): ".$this->GeoResponse);
|
|
return $this->BPStat_Error;
|
|
}
|
|
}
|
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// error messages for routing service
|
|
|
|
if ($servicenum == $this->NR_ROUTINGREQUEST)
|
|
{
|
|
if (($this->RouteStation[1] == "" and $this->RouteStation[2] == "")
|
|
and (($this->BPRequest["CLIENT"]["STATION1"]=="") and ($this->BPRequest["CLIENT"]["STATION2"]=="") ))
|
|
{
|
|
$this->RouteResponse = "Warning: No starting and destination point defined!";
|
|
$this->Log_to_file("ALBasic.BFCheckParam: Regular error message (routing): ".$this->RouteResponse);
|
|
return $this->BPStat_Error;
|
|
}
|
|
}
|
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// error messages for next search service
|
|
|
|
if ($servicenum == $this->NR_NEXTREQUEST)
|
|
{
|
|
if($this->SearchByCoord=="" && $this->SearchByTown=="")
|
|
{
|
|
$this->Response = "Warning: No search statement as SearchByTown or SearchByCoord defined!";
|
|
$this->Log_to_file("ALBasic.BFCheckParam: Regular error message (next search): ".$this->Response);
|
|
return $this->BPStat_Error;
|
|
}
|
|
}
|
|
|
|
$this->Log_to_file("ALBasic.BFCheckParam: Passed Succesfully");
|
|
|
|
return $this->BPStat_Success;
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// BFAddParam
|
|
// add a property to the request without recheck by system
|
|
|
|
function BFAddParam($app, $key, $value)
|
|
{
|
|
$this->BPRequest[strtoupper($app)][strtoupper($key)] = $value;
|
|
$this->Log_to_file("ALBasic.BFAddParam: Passed successfully: ".$app." ".$key." ".$value);
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// BFGetParam
|
|
// read a property directly from COR or ANS part of the TCP/IP answer
|
|
|
|
function BFGetParam($answer_type, $section, $name, $def_value)
|
|
{
|
|
(($answer_type == $this->eATAns) ? $file = "ANS" : $file = "COR");
|
|
|
|
if($this->BCAnswerList[$file][strtoupper($section)][$name]!="")
|
|
return $this->BCAnswerList[$file][strtoupper($section)][$name];
|
|
|
|
$this->Log_to_file("ALBasic.BFGetParam: Passed successfully: ".$answer_type." ".$section." ".$name." ".$def_value);
|
|
return $def_value;
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// BFDeleteOldFiles
|
|
// delete old files which are older than BPMaximumFileAge by random
|
|
// because it takes a lot of time to check and delete files, we only
|
|
// delete every second map generation.
|
|
|
|
function BFDeleteOldFiles()
|
|
{
|
|
if(!$this->BPMapsByStream || $this->BPStreamDirectory=="") return false;
|
|
|
|
$handle = opendir($this->BPStreamDirectory."/");
|
|
while (($file = readdir($handle))!==false)
|
|
if($file!="." && $file!="..")
|
|
if( (time()-filemtime($this->BPStreamDirectory."/".$file))>$this->BPMaximumFileAge*60)
|
|
if(!unlink($this->BPStreamDirectory."/".$file))
|
|
$this->Log_to_file("AlBasic.BFDeleteOldFiles: Error while deltin old map files on hard disk. Path: ".$this->BPStreamDirectory);
|
|
|
|
$this->Log_to_file("AlBasic.BFDeleteOldFiles: Passed successfully . Path: ".$this->BPStreamDirectory);
|
|
// deletion was performed
|
|
return true;
|
|
}
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// Log_to_file
|
|
// write log output to file defined by BPLogFilePath
|
|
|
|
function Log_to_file($logtext)
|
|
{
|
|
if($this->BPLogFilePath=='')
|
|
return false;
|
|
|
|
$fp=@fopen($this->BPLogFilePath,"a");
|
|
if($fp)
|
|
{
|
|
fwrite($fp,$logtext."\r\n");
|
|
fclose($fp);
|
|
}
|
|
else
|
|
echo "<br>Error while writing to log file<br>";
|
|
|
|
return false;
|
|
}
|
|
|
|
} // end of class definition
|
|
|
|
?>
|