_OPT = 'compress';
$this->_SPACER = '';
$this->_CRLF = '';
}
}
$this->_SESSID = getmypid();
$this->_MSGCNT = 0;
}
/**
* Checks a socket for timeout or EOF
* @param int socket handle
* @return boolean true if the socket has timed out or is EOF
*/
function socketStatus(&$fh) {
$return = false;
if (is_resource($fh)) {
$temp = socket_get_status($fh);
if ($temp['timed_out']) $return = true;
if ($temp['eof']) $return = true;
unset($temp);
}
return $return;
}
/**
* Accepts an OPS protocol message or an file handle
* an the data into a PHP array
* @param string OPS message
* @return mixed PHP array, or error
*/
function decode($in) {
$ops_msg = '';
/* determine if we were passed a string or file handle */
if (is_resource($in)) {
# read the file into a string, then process as usual
while (!feof($in)) {
$ops_msg .= fgets($in, 400);
}
} else {
$ops_msg = $in;
}
return $this->XML2PHP($ops_msg); /* decode and return */
}
/**
* XML Parser that converts an OPS protocol message into a PHP array
* @param string OPS message
* @return mixed PHP array, or error
*/
function XML2PHP($msg) {
$this->_data = NULL;
$xp = xml_parser_create();
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
xml_parser_set_option($xp, XML_OPTION_SKIP_WHITE, true);
xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING, 'ISO-8859-1');
if (!xml_parse_into_struct($xp,$msg,$vals,$index)) {
$error = sprintf('XML error: %s at line %d',
xml_error_string(xml_get_error_code($xp)),
xml_get_current_line_number($xp)
);
xml_parser_free($xp);
trigger_error ("oSRS Error - ". $error, E_USER_WARNING);
die();
}
xml_parser_free($xp);
$temp = $depth = array();
foreach($vals as $value) {
switch ($value['tag']) {
case 'OPS_envelope':
case 'header':
case 'body':
case 'data_block':
break;
case 'version':
case 'msg_id':
case 'msg_type':
$key = '_OPS_' . $value['tag'];
$temp[$key] = $value['value'];
break;
case 'item':
// Not every Item has attributes
if (isSet($value['attributes'])) {
$key = $value['attributes']['key'];
} else {
$key = "";
}
switch ($value['type']) {
case 'open':
array_push($depth, $key);
break;
case 'complete':
array_push($depth, $key);
$p = join('::',$depth);
// enn_change - make sure that $value['value'] is defined
if (isSet($value['value'])){
$temp[$p] = $value['value'];
} else {
$temp[$p] = "";
}
array_pop($depth);
break;
case 'close':
array_pop($depth);
break;
}
break;
case 'dt_assoc':
case 'dt_array':
break;
}
}
foreach ($temp as $key=>$value) {
$levels = explode('::',$key);
$num_levels = count($levels);
if ($num_levels==1) {
$this->_data[$levels[0]] = $value;
} else {
$pointer = &$this->_data;
for ($i=0; $i<$num_levels; $i++) {
if ( !isset( $pointer[$levels[$i]] ) ) {
$pointer[$levels[$i]] = array();
}
$pointer = &$pointer[$levels[$i]];
}
$pointer = $value;
}
}
return ($this->_data);
}
/**
* Converts a PHP array into an OPS message
* @param array PHP array
* @return string OPS XML message
*/
function encode($array) {
$this->_MSGCNT++;
$msg_id = $this->_SESSID + $this->_MSGCNT; /* addition removes the leading zero */
$msg_type = $this->_MSGTYPE_STD;
if ($array['protocol']) {
$array['protocol'] = strtoupper($array['protocol']);
}
if ($array['action']) {
$array['action'] = strtoupper($array['action']);
}
if ($array['object']) {
$array['object'] = strtoupper($array['object']);
}
$xml_data_block = $this->PHP2XML($array);
$ops_msg = '' . $this->_CRLF .
'' . $this->_CRLF .
'' . $this->_CRLF .
$this->_SPACER . '' . $this->_CRLF .
$this->_SPACER . $this->_SPACER . '' . $this->_OPS_VERSION . '' . $this->_CRLF .
$this->_SPACER . $this->_SPACER . '' . $msg_id . '' . $this->_CRLF .
$this->_SPACER . $this->_SPACER . '' . $msg_type . '' . $this->_CRLF .
$this->_SPACER . '' . $this->_CRLF .
$this->_SPACER . '' . $this->_CRLF .
$xml_data_block . $this->_CRLF .
$this->_SPACER . '' . $this->_CRLF .
'';
return $ops_msg;
}
/**
* Converts a PHP array into an OPS data_block tag
* @param array PHP array
* @return string OPS data_block tag
*/
function PHP2XML($data) {
return str_repeat($this->_SPACER,2) . '' . $this->_convertData($data, 3) . $this->_CRLF . str_repeat($this->_SPACER,2) . '';
}
/**
* Recursivly converts PHP data into XML
* @param mixed PHP array or data
* @param int ident level
* @return string XML string
*/
function _convertData(&$array, $indent=0) {
$string = '';
$IND = str_repeat($this->_SPACER,$indent);
if (is_array($array)) {
if ($this->_is_assoc($array)) { # HASH REFERENCE
$string .= $this->_CRLF . $IND . '';
$end = '';
} else { # ARRAY REFERENCE
$string .= $this->_CRLF . $IND . '';
$end = '';
}
foreach ($array as $k=>$v) {
$indent++;
/* don't encode some types of stuff */
if ((gettype($v)=='resource') || (gettype($v)=='user function') || (gettype($v)=='unknown type')) {
continue;
}
$string .= $this->_CRLF . $IND . '- _convertData($v, $indent+1);
$string .= $this->_CRLF . $IND . '
';
} else {
$string .= $this->_quoteXMLChars($v) . '';
}
$indent--;
}
$string .= $this->_CRLF . $IND . $end;
} else { # SCALAR
$string .= $this->_CRLF . $IND . '' .
$this->_quoteXMLChars($array) . '';
}
return $string;
}
/**
* Quotes special XML characters
* @param string string to quote
* @return string quoted string
*/
function _quoteXMLChars($string) {
$search = array ('&', '<', '>', "'", '"');
$replace = array ('&', '<', '>', ''', '"');
$string = str_replace($search, $replace, $string);
$string = utf8_encode($string);
return $string;
}
/**
* Determines if an array is associative or not, since PHP
* doesn't really distinguish between the two, but Perl/OPS does
* @param array array to check
* @return boolean true if the array is associative
*/
function _is_assoc(&$array){
if (is_array($array)) {
foreach ($array as $k=>$v) {
if (!is_int($k)) return true;
}
}
return false;
}
}