PEAR();
if (is_array($args)) {
if ($args['option']=='compress') {
$this->_OPT = 'compress';
$this->_SPACER = '';
$this->_CRLF = '';
}
}
$this->_SESSID = getmypid();
$this->_MSGCNT = 0;
$this->_log('raw','i','OPS Raw Log:');
$this->_log('raw','i','Initialized '.date('r') );
$this->_log('xml','i','OPS XML Log:');
$this->_log('xml','i','Initialized '.date('r') );
}
/**
* Writes a message to a socket (buffered IO)
*
* @param int socket handle
*
* @param string message to write
*
*/
function writeData(&$fh,$msg)
{
$len = strlen($msg);
fputs($fh, 'Content-Length: ' . $len . $this->CRLF . $this->CRLF);
fputs($fh, $msg, $len );
$this->_log('raw', 'w', $msg, $len);
}
/**
* Encodes and writes a message to a socket
*
* @param int socket handle
*
* @param string message to encode and write
*
*/
function writeMessage(&$fh, $hr )
{
$msg = $this->encode( $hr );
$this->writeData($fh, $msg );
}
/**
* Reads data from a socket
*
* @param int socket handle
*
* @param int timeout for read
*
* @return mixed buffer with data, or an error for a short read
*
*/
function readData(&$fh, $timeout=5)
{
$len = 0;
/* PHP doesn't have timeout for fread ... we just set the timeout for the socket */
socket_set_timeout($fh, $timeout);
$line = fgets($fh, 4000);
if ($this->socketStatus($fh)) {
return false;
}
if (!$len && preg_match('/^\s*Content-Length:\s+(\d+)\s*\r\n/i', $line, $matches ) ) {
$len = (int)$matches[1];
} else {
$this->_log('raw', 'e', 'UNEXPECTED READ: No Content-Length' );
$this->_log('raw', 'r', $line);
return false;
}
/* read the empty line */
$line = fread($fh, 2);
if ($this->socketStatus($fh)) {
return false;
}
if ($line!=$this->CRLF) {
$this->_log('raw', 'e', 'UNEXPECTED READ: No CRLF');
$this->_log('raw', 'r', $line);
return false;
}
$line = '';
while (strlen($line) < $len) {
$line .= fread($fh, $len);
if ($this->socketStatus($fh)) {
return false;
}
}
if ($line) {
$buf = $line;
$this->_log('raw', 'r', $line);
} else {
$buf = false;
$this->_log('raw', 'e', 'NEXT LINE SHORT READ (should be '.$len.')' );
$this->_log('raw', 'r', $line);
}
return $buf;
}
/**
* Reads and decodes data from a socket
*
* @param int socket handle
*
* @param int timeout for read
*
* @return mixed associative array of data, or an error
*
*/
function readMessage(&$fh, $timeout=5)
{
$buf = $this->readData($fh, $timeout);
return ( $buf ? $this->decode($buf) : false );
}
/**
* 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']) {
$this->_log('raw', 'e', 'SOCKET TIMED OUT');
$return = true;
}
if ($temp['eof']) {
$this->_log('raw', 'e', 'SOCKET EOF');
$return = true;
}
unset($temp);
}
return $return;
}
/**
* Internal method to generate error codes hashes
*
* @param int error code
*
* @param string error message
*
* @return array error hash
*
*/
function _opsError($err_code,$err_text)
{
return array(
'response_code' => $err_code,
'response_text' => $err_text,
'is_success' => 0
);
}
#
# DECODING METHODS
# Converts XML OPS messages into PHP data
#
/**
* Accepts an OPS protocol message or an file handle
* and decodes 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;
}
/* log it first */
$this->_log('xml', 'r', $ops_msg);
/* decode and return */
return $this->XML2PHP($ops_msg);
}
/**
* 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);
return $this->raiseError($error);
}
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':
$key = $value['attributes']['key'];
switch ($value['type']) {
case 'open':
array_push($depth, $key);
break;
case 'complete':
array_push($depth, $key);
$p = join('::',$depth);
$temp[$p] = $value['value'];
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);
}
#
# ENCODING METHODS
# Converts PHP data into XML OPS messages
#
/**
* 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 .
'
'; foreach ($this->log[$log] as $line) { switch ($format) { case 'raw': echo $line . "\n"; break; case 'html': default: echo htmlEntities($line) . "\n"; break; } } echo ''; } }