Source for file Protocol.inc

Documentation is available at Protocol.inc

  1. <?php /*-*- mode: php; tab-width:4 -*-*/
  2.  
  3.   /* java_Protocol.php -- PHP/Java Bridge protocol implementation
  4.  
  5.   Copyright (C) 2003-2007 Jost Boekemeier
  6.  
  7.   This file is part of the PHP/Java Bridge.
  8.  
  9.   The PHP/Java Bridge ("the library") is free software; you can
  10.   redistribute it and/or modify it under the terms of the GNU General
  11.   Public License as published by the Free Software Foundation; either
  12.   version 2, or (at your option) any later version.
  13.  
  14.   The library is distributed in the hope that it will be useful, but
  15.   WITHOUT ANY WARRANTY; without even the implied warranty of
  16.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.   General Public License for more details.
  18.  
  19.   You should have received a copy of the GNU General Public License
  20.   along with the PHP/Java Bridge; see the file COPYING.  If not, write to the
  21.   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  22.   02111-1307 USA.
  23.  
  24.   Linking this file statically or dynamically with other modules is
  25.   making a combined work based on this library.  Thus, the terms and
  26.   conditions of the GNU General Public License cover the whole
  27.   combination.
  28.  
  29.   As a special exception, the copyright holders of this library give you
  30.   permission to link this library with independent modules to produce an
  31.   executable, regardless of the license terms of these independent
  32.   modules, and to copy and distribute the resulting executable under
  33.   terms of your choice, provided that you also meet, for each linked
  34.   independent module, the terms and conditions of the license of that
  35.   module.  An independent module is a module which is not derived from
  36.   or based on this library.  If you modify this library, you may extend
  37.   this exception to your version of the library, but you are not
  38.   obligated to do so.  If you do not wish to do so, delete this
  39.   exception statement from your version. */
  40.  
  41. require_once ("${JAVA_BASE}/Options.inc");
  42. require_once ("${JAVA_BASE}/Client.inc");
  43.  
  44. /**
  45.  * @access private
  46.  */
  47. class java_SocketChannel {
  48.   public $peer$protocol;
  49.   private $channelName$host;
  50.  
  51.   function java_SocketChannel($peer$protocol$host$channelName{
  52.     $this->peer $peer;
  53.     $this->protocol $protocol;
  54.     $this->host $host;
  55.     $this->channelName $channelName;
  56.   }
  57.   function fwrite($data{
  58.     return fwrite($this->peer$data);
  59.   }
  60.   function fread($size{
  61.     return fread($this->peer$size);
  62.   }
  63.   function keepAlive({
  64.     // keep alive, required by protocol
  65.     $this->fwrite("<F p=\"A\" />");
  66.     $this->fread(10)// <F p="A"/>
  67.   }
  68. }
  69. /**
  70.  * @access private
  71.  */
  72. class java_EmptyPipeChannel {
  73.   function open($handler{
  74.       if (false$handler $handler;
  75.     throw new java_RuntimeException("protocol error: socket channel names must not start with a slash");
  76.   }
  77.   function getName({
  78.     return null;
  79.   }
  80.   function keepAlive({}
  81. }
  82. /**
  83.  * @access private
  84.  */
  85. class java_PipeChannel extends java_EmptyPipeChannel {
  86.   public $peer$peerr$peerr_desc$name;
  87.   public $fifo$fifor;
  88.   public $iname$oname;
  89.  
  90.   function java_PipeChannel($name{
  91.     $this->name $name;
  92.     $this->iname $this->name ".i";
  93.     $mask umask(0);
  94.     $this->fifor posix_mkfifo($this->iname0666);
  95.     $this->oname $this->name ".o";
  96.     $this->fifo posix_mkfifo($this->oname0666);
  97.     umask($mask);
  98.   }
  99.   function open($handler{
  100.       if (false$handler $handler;
  101.       
  102.     $this->peerr fopen($this->iname"r");
  103.     $this->peerr_desc array($this->peerr);
  104.     stream_set_blocking($this->peerrfalse);
  105.     stream_set_timeout($this->peerr-1);
  106.  
  107.     $this->peer fopen($this->oname"w");
  108.     unlink($this->iname);
  109.     unlink($this->oname);
  110.     unlink($this->name);
  111.     stream_set_timeout($this->peer-1);
  112.     return $this;
  113.   }
  114.   function fwrite($data{
  115.       return fwrite($this->peer$data);
  116.   }
  117.   function fread($size{
  118.     static $empty NULL;
  119.     stream_select($this->peerr_desc$empty$empty1677216);
  120.     return fread($this->peerr$size);
  121.   }
  122.   function getName({
  123.     return $this->name;
  124.   }
  125. }
  126.  
  127. /**
  128.  * @access private
  129.  */
  130. class java_SocketHandler {
  131.   public $protocol$channel;
  132.  
  133.   function java_SocketHandler($protocol$channel{
  134.     $this->protocol $protocol;
  135.     $this->channel $channel;
  136.   }
  137.   function write($data{
  138.       return $this->channel->fwrite($data);
  139.   }
  140.   function read($size{
  141.     return $this->channel->fread($size);
  142.   }
  143.   function redirect({}
  144.   function keepAlive({
  145.     $this->channel->keepAlive();
  146.   }
  147. }
  148. /**
  149.  * @access private
  150.  */
  151. class java_HttpHandler extends java_SocketHandler {
  152.   public $headers;
  153.   public $redirect;
  154.   
  155.   public $context$ssl$port// used by reopen
  156.   public $host// used when creating a socket channel lazily. the port# is passed via X_JAVABRIDGE_CHANNEL
  157.  
  158.   public $socket// we write to the socket directly and keep the pipe channel for later use
  159.   
  160.   function createPipeChannel($host$pipe_dir{
  161.     if(!is_null($pipe_dir&& ($host == "127.0.0.1" || (substr($host,0,9== "localhost")))
  162.       return new java_PipeChannel(tempnam($pipe_dir".php_java_bridge"));
  163.     return new java_EmptyPipeChannel();
  164.   }
  165.   function close({
  166.     fclose($this->socket);
  167.   }
  168.   function open({
  169.       $errno null$errstr null;
  170.   /* Do not pfsockopen here, the J2EE server may not be able to handle
  171.     hundreds of persistent connections to the servlet very well */
  172.     $socket fsockopen("{$this->ssl}{$this->host}", $this->port$errno$errstr30);
  173.     if (!$socketthrow new java_RuntimeException("Could not connect to the J2EE server {$this->ssl}{$this->host}:{$this->port}Please start itfor example with the command: \"java -jar JavaBridge.jar SERVLET:8080 3 JavaBridge.log\" orif the back end has been compiled to native codewith \"modules/java SERVLET:8080 3 JavaBridge.log\". Error message$errstr ($errno)\n");
  174.     stream_set_timeout($socket, -1);
  175.     return $socket;
  176.   }
  177.   function java_HttpHandler($protocol, $ssl, $host, $port) {
  178.     $this->protocol $protocol;
  179.     $this->ssl $ssl;
  180.     $this->host $host;
  181.     $this->port $port;
  182.     $this->channel $this->createPipeChannel($host$protocol->client->RUNTIME['PIPE_DIR']);
  183.     $this->socket $this->open();
  184.   }
  185.   function getCookies() {
  186.     $str="";
  187.     $first=true;
  188.     foreach($_COOKIE as $k => $v) {
  189.       $str .= ($first ? "Cookie$k=$v":"$k=$v");
  190.       $first=false;
  191.     }
  192.     if(!$first) $str .= "\r\n";
  193.     return $str;
  194.   }
  195.   function getContextFromCgiEnvironment() {
  196.     $ctx = array_key_exists('X_JAVABRIDGE_CONTEXT', $_SERVER)
  197.               ?$_SERVER['X_JAVABRIDGE_CONTEXT']
  198.               :null;
  199.     return $ctx;
  200.   }
  201.   function getChannelName() {
  202.     $name = $this->channel->getName();
  203.     return !is_null($namesprintf("X_JAVABRIDGE_CHANNEL: %s\r\n"$namenull;
  204.   }
  205.   function getContext() {
  206.     $ctx = $this->getContextFromCgiEnvironment();
  207.     $context "";
  208.     if($ctx{
  209.       $context = sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n", $ctx);
  210.     }
  211.     return $context;
  212.   }
  213.   function getWebAppInternal() {
  214.     // from createHttpHandler
  215.     $context = $this->protocol->webContext;
  216.     if(isset($context)) return $context;
  217.  
  218.     /* Coerce a http://xyz.com/kontext/foo.php request to the back
  219.        end: http://xyz.com:{java_hosts[0]}/kontext/foo.php.  For
  220.        example if we receive a request:
  221.        http://localhost/sessionSharing.php and java.servlet is On and
  222.        java.hosts is "127.0.0.1:8080" the code would connect to the
  223.        back end:
  224.        http://127.0.0.1:8080/sessionSharing.phpjavabridge. This
  225.        creates a cookie with PATH value "/".  If java_servlet is User
  226.        the request http://localhost/myContext/sessionSharing.php the
  227.        code would connect to
  228.        http://127.0.0.1/myContext/sessionSharing.phpjavabridge and a
  229.        cookie with a PATH value "/myContext" would be created.
  230.     */
  231.     return (JAVA_SERVLET == "User" &&
  232.             array_key_exists('PHP_SELF'$_SERVER&&
  233.             array_key_exists('HTTP_HOST'$_SERVER))
  234.       ? $_SERVER['PHP_SELF']."javabridge"
  235.       : null;
  236.   }
  237.   function getWebApp() {
  238.     $context = $this->getWebAppInternal();
  239.     if(is_null($context&& JAVA_SERVLET=="On"$context JAVA_SERVLET;
  240.     if(is_null($context|| $context[0]!="/"
  241.       $context "/JavaBridge/JavaBridge.phpjavabridge";
  242.     return $context;
  243.   }
  244.  
  245.   function write($data) {
  246.  
  247.     $compatibility = $this->protocol->client->RUNTIME["PARSER"]=="NATIVE"
  248.       ? chr(0103-JAVA_PREFER_VALUES)
  249.       : chr(0100+JAVA_PREFER_VALUES);
  250.     if(is_int(JAVA_LOG_LEVEL)) {
  251.       $compatibility |= 128 | (7 & JAVA_LOG_LEVEL)<<2;
  252.     }
  253.  
  254.     $this->headers null;
  255.     $socket $this->socket;
  256.     $len strlen($data);
  257.     $webapp $this->getWebApp();
  258.     $cookies $this->getCookies();
  259.     $channel $this->getChannelName();
  260.     $context $this->getContext();
  261.     $redirect $this->redirect;
  262.     $res "PUT ";
  263.     $res .= $webapp;
  264.     $res .= " HTTP/1.0\r\n";
  265.     $res .= "Host: localhost\r\n";
  266.     $res .= "Content-Length: "$res .= $len$res .= "\r\n";
  267.     $res .= $context;
  268.     $res .= $cookies;
  269.     $res .= $redirect;
  270.     if(!is_null($channel)) $res .= $channel;
  271.     $res .= "\r\n";
  272.     $res .= "\177";
  273.     $res .= $compatibility;
  274.     $res .= $data;
  275.     $count fwrite($socket$res)fflush($socket);
  276.     return $count;
  277.   }
  278.   function doSetCookie($key, $val, $path) {
  279.     $path=trim($path);
  280.  
  281.     $webapp = $this->getWebAppInternal()if(!$webapp$path="/";
  282.     setcookie($key$val0$path);
  283.   }
  284.   function parseHeaders() {
  285.     $this->headers array();
  286.     while (($str trim(fgets($this->socketJAVA_RECV_SIZE)))) {
  287.       if($str[0]=='X') {
  288.         if(!strncasecmp("X_JAVABRIDGE_REDIRECT", $str, 21)) {
  289.           $this->headers["redirect"]=trim(substr($str22));
  290.         } else if(!strncasecmp("X_JAVABRIDGE_CONTEXT", $str, 20)) {
  291.           $this->headers["context"]=trim(substr($str21));
  292.         }
  293.       } else if($str[0]=='S') {    // Set-Cookie:
  294.         if(!strncasecmp("SET-COOKIE", $str, 10)) {
  295.           $str=substr($str, 12);
  296.           $ar = explode(";", $str);
  297.           $cookie = explode("=",$ar[0]);
  298.           $path = "";
  299.           if(isset($ar[1])) $p=explode("=", $ar[1]);
  300.           if(isset($p)) $path=$p[1];
  301.           $this->doSetCookie($cookie[0]$cookie[1]$path);
  302.         }
  303.       } else if($str[0]=='C') { // Content-Length
  304.         if(!strncasecmp("CONTENT-LENGTH", $str, 14)) {
  305.           $this->headers["content_length"]=trim(substr($str15));
  306.         }
  307.       }
  308.     }
  309.   }
  310.   function read($size) {
  311.       if (false) $size = $size;
  312.       
  313.      if(is_null($this->headers)) $this->parseHeaders();
  314.     $data fread($this->socket$this->headers['content_length']);
  315.     return $data;
  316.   }
  317.  
  318.   function getChannel($channelName) {
  319.       $errstr = null; $errno = null;
  320.     if($channelName[0]=='/') return $this->channel->open($this);
  321.     $peer pfsockopen($this->host$channelName$errno$errstr30);
  322.     if (!$peerthrow new java_RuntimeException("Could not connect to the context server {$this->host}:{$channelName}Error message$errstr ($errno)\n");
  323.     stream_set_timeout($peer, -1);
  324.     return new java_SocketChannel($peer, $this->protocol$this->host$channelName);
  325.   }
  326.  
  327.   function redirect() {
  328.     if(!isset($this->headers["redirect"])) { // no redirect received: must continue to send PUT requests
  329.       throw new java_RuntimeException("no Pipe- or SocketContextServer available.");
  330.     }
  331.     if(!isset($this->protocol->socketHandler)) {
  332.       $hostVec = java_Protocol::getHost();
  333.       $this->host $hostVec[0];
  334.       $channelName $this->headers["redirect"];
  335.       $context $this->headers["context"];
  336.       $len strlen($context);
  337.       $len0 chr(0xFF);
  338.       $len1 chr($len&0xFF)$len>>=8;
  339.       $len2 chr($len&0xFF);
  340.       $this->protocol->socketHandler=new java_SocketHandler($this->protocol$this->getChannel($channelName));
  341.       $this->protocol->write("\177${len0}${len1}${len2}${context}");
  342.       $this->context sprintf("X_JAVABRIDGE_CONTEXT: %s\r\n"$context);
  343.     }
  344.     $this->close();
  345.     $this->protocol->handler $this->protocol->socketHandler;
  346.   }
  347. }
  348.  
  349. /**
  350.  * @access private
  351.  */
  352. class java_Protocol {
  353.   public $client;
  354.   public $webContext;
  355.   public $serverName;
  356.  
  357.   function getOverrideHosts() {
  358.       if(array_key_exists('X_JAVABRIDGE_OVERRIDE_HOSTS', $_ENV)) {
  359.           $override = $_ENV['X_JAVABRIDGE_OVERRIDE_HOSTS'];
  360.           if(!is_null($override) && $override!='/') return $override;
  361.       }
  362.       // fcgi: override for redirect
  363.       return 
  364.         array_key_exists('X_JAVABRIDGE_OVERRIDE_HOSTS_REDIRECT', $_SERVER)
  365.            ?$_SERVER['X_JAVABRIDGE_OVERRIDE_HOSTS_REDIRECT']
  366.            :null;
  367.   }
  368.   static function getHost() {
  369.     static $host;
  370.     if(!isset($host)) {
  371.       $hosts = explode(";", JAVA_HOSTS);
  372.       $host = explode(":", $hosts[0]); // TODO: check host list
  373.     }
  374.     return $host;
  375.   }
  376.   function createHttpHandler() {
  377.     $hostVec = java_Protocol::getHost();
  378.     $host = $hostVec[0];
  379.     $port = $hostVec[1];
  380.  
  381.     $overrideHosts = $this->getOverrideHosts();
  382.     $ssl "";
  383.     if($overrideHosts{
  384.       // handle "s:127.0.0.1:8080//JavaBridge/test.phpjavabridge" 
  385.       // or "s:127.0.0.1:8080" 
  386.       // or "/" 
  387.       // or ""
  388.      $s=$overrideHosts;
  389.      if((strlen($s)>2) && ($s[1]==':')) {
  390.        if($s[0]=='s')
  391.          $ssl="ssl://";
  392.        $s = substr($s, 2);
  393.      }
  394.      $webCtx = strpos($s, "//");
  395.      if($webCtx)
  396.        $host = substr($s, 0, $webCtx);
  397.      else
  398.        $host = $s;
  399.  
  400.      $idx = strpos($host, ':');
  401.      if($idx) {
  402.        if($webCtx)
  403.          $port = substr($host, $idx+1, $webCtx);
  404.        else
  405.          $port = substr($host, $idx+1);
  406.        $host = substr($host, 0, $idx);
  407.      } else {
  408.        $port = "8080";
  409.      }
  410.  
  411.      if($webCtx) $webCtx = substr($s, $webCtx+1);
  412.       $this->webContext $webCtx;
  413.     }
  414.     $this->serverName "$host:$port";
  415.     return new java_HttpHandler($this, $ssl, $host, $port);
  416.   }
  417.   /**
  418.    * connect to a local channel (no servlet engine or app server)
  419.    */
  420.   function createSimpleHandler($channelName) {
  421.     if(!is_string($channelName)) {
  422.       $errno = null; $errstr = null;
  423.       $peer = pfsockopen($host="127.0.0.1", $channelName, $errno, $errstr, 30);
  424.     } else {
  425.       $type = $channelName[0];
  426.       if($type=='@' || $type=='/') {         // unix domain socket
  427.         if($type=='@') $channelName[0]="\0"; // abstract name space
  428.         $peer = pfsockopen($host="unix://${channelName}", null, $errno, $errstr, 30);
  429.         $channelName = null;
  430.       }
  431.       else {                    // tcp socket
  432.         list($host, $channelName) = explode(":", $channelName);
  433.         $peer = pfsockopen($host, $channelName, $errno, $errstr, 30);
  434.       }
  435.     }
  436.     if (!$peer) throw new java_RuntimeException("Could not connect to the context server $channelNameError message$errstr ($errno)\n");
  437.     stream_set_timeout($peer, -1);
  438.     $handler = new java_SocketHandler($this, new java_SocketChannel($peer, $this, $host, $channelName));
  439.  
  440.     $compatibility = $this->client->RUNTIME["PARSER"]=="NATIVE"
  441.       ? chr(0103-JAVA_PREFER_VALUES)
  442.       : chr(0100+JAVA_PREFER_VALUES);
  443.     
  444.     if(is_int(JAVA_LOG_LEVEL)) {
  445.       $compatibility |= 128 | (7 & JAVA_LOG_LEVEL)<<2;
  446.     }
  447.     $this->write("\177$compatibility");
  448.     $this->serverName "127.0.0.1:$channelName";
  449.     return $handler;
  450.   }
  451.   function createHandler() {
  452.     if(!array_key_exists('X_JAVABRIDGE_OVERRIDE_HOSTS_REDIRECT', $_SERVER)
  453.      && function_exists("java_get_default_channel") &&
  454.       ($defaultChannel=java_get_default_channel())) {
  455.       // if bind.c has started a local back end from Apache/IIS
  456.       return $this->createSimpleHandler($defaultChannel);
  457.     } else {
  458.       return $this->createHttpHandler();
  459.     }
  460.   }
  461.   function java_Protocol ($client) {
  462.     $this->client $client;
  463.     $this->handler $this->createHandler();
  464.   }
  465.  
  466.   function redirect() {
  467.     $this->handler->redirect();
  468.   }
  469.  
  470.   function read($size) {
  471.     return $this->handler->read($size);
  472.   }
  473.  
  474.   function sendData() {
  475.     $this->handler->write($this->client->sendBuffer);
  476.     $this->client->sendBuffer=null;
  477.   }
  478.   function flush() {
  479.     if(JAVA_DEBUG) {
  480.       echo "sending::: "; echo $this->client->sendBufferecho "\n";
  481.     }
  482.     $this->sendData();
  483.   }
  484.   function keepAlive() {
  485.     $this->handler->keepAlive();
  486.   }
  487.   function handle() {
  488.     $this->client->handleRequests();
  489.   }
  490.   function write($data) {
  491.     $this->client->sendBuffer.=$data;
  492.   }
  493.   function finish() {
  494.     $this->flush();
  495.     $this->handle();
  496.     $this->redirect();
  497.   }
  498.   
  499.   function referenceBegin($name) {
  500.     $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
  501.     if(JAVA_DEBUG{
  502.       echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";
  503.     }
  504.     $this->client->preparedToSendBuffer=null;
  505.  
  506.     $signature=sprintf("<H p=\"1\" v=\"%s\">"$name);
  507.     $this->write($signature);
  508.     $signature[6]="2";
  509.     $this->client->currentArgumentsFormat $signature;
  510.   }
  511.   function referenceEnd() {
  512.     $this->client->currentArgumentsFormat.=$format="</H>";
  513.     $this->write($format);
  514.     $this->finish();
  515.     $this->client->currentCacheKey=null;
  516.   }
  517.   function createObjectBegin($name) {
  518.     $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
  519.     if(JAVA_DEBUG{
  520.       echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";
  521.     }
  522.     $this->client->preparedToSendBuffer=null;
  523.  
  524.     $signature=sprintf("<K p=\"1\" v=\"%s\">"$name);
  525.     $this->write($signature);
  526.     $signature[6]="2";
  527.     $this->client->currentArgumentsFormat $signature;
  528.   }
  529.   function createObjectEnd() {
  530.     $this->client->currentArgumentsFormat.=$format="</K>";
  531.     $this->write($format);
  532.     $this->finish();
  533.     $this->client->currentCacheKey=null;
  534.   }
  535.   function propertyAccessBegin($object, $method) {
  536.     $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
  537.     if(JAVA_DEBUG{
  538.       echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";
  539.     }
  540.     $this->client->preparedToSendBuffer=null;
  541.  
  542.     $this->write(sprintf("<G p=\"1\" v=\"%x\" m=\"%s\">"$object$method));
  543.     $this->client->currentArgumentsFormat="<G p=\"2\" v=\"%x\" m=\"${method}\">";
  544.   }
  545.   function propertyAccessEnd() {
  546.     $this->client->currentArgumentsFormat.=$format="</G>";
  547.     $this->write($format);
  548.     $this->finish();
  549.     $this->client->currentCacheKey=null;
  550.   }
  551.   function invokeBegin($object, $method) {
  552.     $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
  553.     if(JAVA_DEBUG{
  554.       echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";
  555.     }
  556.     $this->client->preparedToSendBuffer=null;
  557.  
  558.     $this->write(sprintf("<Y p=\"1\" v=\"%x\" m=\"%s\">"$object$method));
  559.     $this->client->currentArgumentsFormat="<Y p=\"2\" v=\"%x\" m=\"${method}\">";
  560.   }
  561.   function invokeEnd() {
  562.     $this->client->currentArgumentsFormat.=$format="</Y>";
  563.     $this->write($format);
  564.     $this->finish();
  565.     $this->client->currentCacheKey=null;
  566.   }
  567.   function resultBegin() {
  568.     $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
  569.     if(JAVA_DEBUG{
  570.       echo "flushed preparedToSendBuffer: ".$this->client->preparedToSendBuffer."\n";
  571.     }
  572.     $this->client->preparedToSendBuffer=null;
  573.     
  574.     $this->write("<R>");
  575.   }
  576.   function resultEnd() {
  577.     $this->client->currentCacheKey=null;
  578.     $this->write("</R>");
  579.     $this->flush();
  580.   }
  581.   function writeString($name) {
  582.     $this->client->currentArgumentsFormat.=$format="<S v=\"%s\"/>";
  583.     $this->write(sprintf($formathtmlspecialchars($nameENT_COMPAT)));
  584.  
  585.   }
  586.   function writeBoolean($boolean) {
  587.     $this->client->currentArgumentsFormat.=$format="<T v=\"%s\"/>";
  588.     $this->write(sprintf($format$boolean));
  589.   }
  590.   function writeLong($l) {
  591.     $this->client->currentArgumentsFormat.="<J v=\"%d\"/>";
  592.     if($l<0{
  593.       $this->write(sprintf("<L v=\"%x\" p=\"A\"/>",-$l));
  594.     } else {
  595.       $this->write(sprintf("<L v=\"%x\" p=\"O\"/>",$l));
  596.     }
  597.   }
  598.   function writeULong($l) {
  599.     $this->client->currentArgumentsFormat.=$format="<L v=\"%x\" p=\"O\"/>";
  600.     $this->write(sprintf($format,$l));
  601.   }
  602.   function writeDouble($d) {
  603.     $this->client->currentArgumentsFormat.=$format="<D v=\"%.14e\"/>";
  604.     $this->write(sprintf($format$d));
  605.   }
  606.   function writeObject($object) {
  607.     $this->client->currentArgumentsFormat.=$format="<O v=\"%x\"/>";
  608.     $this->write(sprintf($format$object));
  609.   }
  610.  
  611.   /* the following routines are not cached */
  612.   function writeException($object, $str) {
  613.     $this->write(sprintf("<E v=\"%x\" m=\"%s\"/>",$objecthtmlspecialchars($strENT_COMPAT)));
  614.   }
  615.   function writeCompositeBegin_a() {
  616.     $this->write("<X t=\"A\">");
  617.   }
  618.   function writeCompositeBegin_h() {
  619.     $this->write("<X t=\"H\">");
  620.   }
  621.   function writeCompositeEnd() {
  622.     $this->write("</X>");
  623.   }
  624.   function writePairBegin_s($key) {
  625.     $this->write(sprintf("<P t=\"S\" v=\"%s\">"htmlspecialchars($keyENT_COMPAT)));
  626.   }
  627.   function writePairBegin_n($key) {
  628.     $this->write(sprintf("<P t=\"N\" v=\"%x\">",$key));
  629.   }
  630.   function writePairBegin() {
  631.     $this->write("<P>");
  632.   }
  633.   function writePairEnd() {
  634.     $this->write("</P>");
  635.   }
  636.   function writeUnref($object) {
  637.     $this->client->sendBuffer.=$this->client->preparedToSendBuffer;
  638.     //echo "clear prepared to send buffer\n";
  639.     $this->client->preparedToSendBuffer=null;
  640.     $this->write(sprintf("<U v=\"%x\"/>"$object));
  641.   }
  642.  
  643.   function getServerName() {
  644.     return $this->serverName;
  645.   }
  646. }

Documentation generated on Sun, 16 Mar 2008 19:11:50 +0100 by phpDocumentor 1.4.0a2