<?php  // Must be on the very first line

// This file is part of the BrowserHawk4J software and provided under the
// terms and conditions of the BrowserHawk4J End User License Agreement.
// Copyright (c) 2006-2010 cyScape, Inc. All rights reserved.


// These global statements help when this file is included via a function
// The underscore variables should be considered "private"
GLOBAL $BrowserHawk, $options, $info, $UNSUPPORTED;
GLOBAL $_req, $_res, $_StringClass, $_DoubleClass, $_BooleanClass, $_IntegerClass;

$_StringClass = new JavaClass("java.lang.String");
$_DoubleClass = new JavaClass("java.lang.Double");
$_BooleanClass = new JavaClass("java.lang.Boolean");
$_IntegerClass = new JavaClass("java.lang.Integer");

class Wrap {
  var $obj;
  function __construct($obj) {
    $this->obj = $obj;
  }
  function __get($var) {
    return $this->obj->$var;
  }
  function __call($function, $args) {
    GLOBAL $_StringClass, $_DoubleClass, $_BooleanClass, $_IntegerClass;
    if (count($args) == 0) {
      $retval = $this->obj->$function();
    }
    else if (count($args) == 1) {
      $retval = $this->obj->$function($args[0]);
    }
    else if (count($args) == 2) {
      $retval = $this->obj->$function($args[0], $args[1]);
    }
    else if (count($args) == 3) {
      $retval = $this->obj->$function($args[0], $args[1], $args[2]);
    }
    else {
      $retval = $this->obj->$function($args);  // XXX broken
    }
    if (get_class($retval) == "Java" && java_instanceof($retval, $_StringClass)) {
      return (string) $retval;
    }
    if (get_class($retval) == "Java" && java_instanceof($retval, $_DoubleClass)) {
      return (double) $retval;
    }
    if (get_class($retval) == "Java" && java_instanceof($retval, $_BooleanClass)) {
      return (boolean) $retval;
    }
    if (get_class($retval) == "Java" && java_instanceof($retval, $_IntegerClass)) {
      return (integer) $retval;
    }
    else if (get_class($retval) == "Java") {
      return new Wrap($retval);
    }
    else if (get_class($retval) == "JavaArray") {
      foreach ($retval as $retvalitem) {
        $retvalarray[] = new Wrap($retvalitem);  // wrap each item of the array
      }
      return $retvalarray;
    }
    else {
      return $retval;
    }
  }
}

  //ob_start();

  /* * * * * * REQUEST CALLBACK METHODS * * * * * */

  function getParameter($s) {
    $s = (string) $s;  // Needed in some cases
    if (isset($_GET[$s]))
      return $_GET[$s];
    else if (isset($_POST[$s]))
      return $_POST[$s];
    else
      return null;
  }
  function getHeader($s) {
    $s = strtolower($s);
    if ($s == "user-agent") {
      if (isset($_SERVER['HTTP_USER_AGENT']))
        return $_SERVER['HTTP_USER_AGENT'];
      else
        return null;
    }
    else if ($s == "accept") {
      if (isset($_SERVER['HTTP_ACCEPT']))
        return $_SERVER['HTTP_ACCEPT'];
      else
        return null;
    }
    else if ($s == "accept-language") {
      if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
        return $_SERVER['HTTP_ACCEPT_LANGUAGE'];
      else
        return null;
    }
    else if ($s == "accept-encoding") {
      if (isset($_SERVER['HTTP_ACCEPT_ENCODING']))
        return $_SERVER['HTTP_ACCEPT_ENCODING'];
      else
        return null;
    }
    else if ($s == "via") {
      if (isset($_SERVER['HTTP_VIA']))
        return $_SERVER['HTTP_VIA'];
      else
        return null;
    }
    else if ($s == "x-up-subno") {
      if (isset($_SERVER['HTTP_X_UP_SUBNO']))
        return $_SERVER['HTTP_X_UP_SUBNO'];
      else
        return null;
    }
    else if ($s == "x-up-uplink") {
      if (isset($_SERVER['HTTP_X_UP_UPLINK']))
        return $_SERVER['HTTP_X_UP_UPLINK'];
      else
        return null;
    }
  }
  function getMethod() { return $_SERVER['REQUEST_METHOD']; }
  function getQueryString() { return $_SERVER['QUERY_STRING']; }
  function getScheme() {
    if (isset($_SERVER['HTTPS']) && strlen($_SERVER['HTTPS']))
      return "https";
    else
      return "http";
  }
  function getAttribute($s) { return null; }
  function getRequestURI() {
    // Using SCRIPT_NAME works fairly well, but REQUEST_URI may be better
    // when URL rewriting is in play.  We cut off the query string as Java
    // doesn't include that, and we're imitating Java.
    $uri = $_SERVER['REQUEST_URI'];
    $quest = strpos($uri, '?');
    if ($quest === false) {
      return $uri;
    }
    else {
      return substr($uri, 0, $quest);
    }
  }
  function getRemoteAddr() { return $_SERVER['REMOTE_ADDR']; }
  function getServerName() { return $_SERVER['SERVER_NAME']; }
  function getServerPort() { return $_SERVER['SERVER_PORT']; }
  function getContextPath() { return ""; }  // No such notion in PHP
  function getCookies() {
    $arr = array();
    foreach ($_COOKIE as $key => $value) {
      $arr[] = new Java("javax.servlet.http.Cookie", $key, $value);
    }
    return count($arr) > 0 ? $arr : null;
  }
  function getParameterNames() {
    $arr = array();
    foreach ($_GET as $key => $value) {
      $arr[] = $key;
    }
    foreach ($_POST as $key => $value) {
      $arr[] = $key;
    }
    $arrays = new JavaClass("java.util.Arrays");
    $list = $arrays->asList($arr);
    $vect = new Java("java.util.Vector", $list);
    return $vect->elements();
  }
  function getSession($create = true) {
    // We can't return java_session() directly because that call can return
    // a php.java.servlet.HttpSessionFacade which implements ISession but
    // neither of these are javax.servlet.http.HttpSession implementations, so
    // this causes a class cast exception.  So what we do here is return a
    // closure which calls back to PHP, and we use java_session() in the
    // callback.
    return java_closure(null, array("getAttribute" => "getAttribute2"),
                 array(new JavaClass("javax.servlet.http.HttpSession")));
  }
  function toString() { // for debugging
    $arr = array();
    foreach ($_GET as $key => $value) {
      $arr[] = $key;
    }
    foreach ($_POST as $key => $value) {
      $arr[] = $key;
    }
    return $arr;
  }

  /* * * * * * RESPONSE CALLBACK METHODS * * * * * */

  function setContentLength($val) {
    header("Content-Length: " . $val);
  }
  function setContentType($val) {
    header("Content-Type: " . $val);
  }
  function setHeader($name, $val) {
    header("$name: " . $val); // trust the caller not to use colons
  }
  function addHeader($name, $val) {
    header("$name: " . $val, false);  // false means add
  }
  function setDateHeader($name, $val) {
    $val = (float) $val;  // Needed in some cases
    header("$name: " . date("D, d M Y H:i:s T", floor($val / 1000)));
  }
  function addCookie($cook) {
    $name = $cook->getName();
    $value = $cook->getValue();
    $maxAge = $cook->getMaxAge();
    $expire = 0;  // default is session cookie
    if ($maxAge != -1) {
      $expire = time() + $maxAge;
    }
    $path = $cook->getPath();
    $domain = $cook->getDomain();
    $secure = $cook->getSecure();
    setcookie($name, $value, $expire, $path, $domain, $secure);
  }
  function encodeUrl($s) {
    return $s;  // No encoding needed in PHP
  }
  function reset2() {
    if (ob_get_length() > 0) {  // Only if there is something in a buffer
      ob_clean();  // php 4.2.0 introduced this
    }
  }
  function getWriter() {  // has to return a PrintWriter
    $channel = java_closure(null, null,
               array(new JavaClass("java.nio.channels.WritableByteChannel")));
    $channels = new JavaClass("java.nio.channels.Channels");
    $writer = $channels->newWriter($channel, "ISO-8859-1");
    $printWriter = new Java("java.io.PrintWriter", $writer, false);
    return $printWriter;
  }

  /* * * * * * WritableByteChannel CALLBACK METHODS * * * * * */

  // Called when the PrintWriter is flushed, about every 8k written
  function write($byteBuffer) {
    $array = $byteBuffer->array();
    $position = $byteBuffer->position();
    $remaining = $byteBuffer->remaining();
    echo substr($array, $position, $remaining);
    $byteBuffer->compact();
    return $remaining;
  }

  /* * * * * * HttpSession CALLBACK METHODS * * * * * */

  function setAttribute($name, $value) {
    $ses = java_session();
    $ses->put($name, $value);
  }
  function getAttribute2($name) {
    $ses = java_session();
    return $ses->get($name);
  }
  // The other session methods aren't called by BrowserHawk


  /* * * * * * REQUEST/RESPONSE CONSTRUCTION * * * * * */

  $_req = java_closure(null, null,
             array(new JavaClass("javax.servlet.http.HttpServletRequest")));

  $_res = java_closure(null, array("reset" => "reset2"),
             array(new JavaClass("javax.servlet.http.HttpServletResponse")));


  /* * * * * * SUPPORT OBJECTS * * * * * */

  $BrowserHawk = new JavaClass("com.cyscape.browserhawk.BrowserHawk");
  $ExtendedBrowserInfo = new JavaClass("com.cyscape.browserhawk.ExtendedBrowserInfo");
  $UNSUPPORTED = $ExtendedBrowserInfo->UNSUPPORTED;
  $options = new Java("com.cyscape.browserhawk.ExtendedOptions");

  $info = $BrowserHawk->getBrowserInfo($_req);
  // Beginning with PHP 5, the PHP Java Bridge returns Java objects rather
  // than PHP types, even for simple strings, ints, etc.  So as we'd prefer
  // PHP types, we wrap the objects and massage the return values.
  if (version_compare(phpversion(), "5.0.0", ">=")) {
    $BrowserHawk = new Wrap($BrowserHawk);
    $info = new Wrap($info);
    $options = new Wrap($options);
  }

  // Utility function so PHP booleans prints as "true" or "false" rather than
  // "1" or "".
  function boolprint($b) {
    if ($b === false)
      print "false";
    else if ($b === true)
      print "true";
    else
      print (string) $b;
  }

  function bhextended($opts) {
    GLOBAL $BrowserHawk, $_req, $_res;
    if (version_compare(phpversion(), "5.0.0", ">=")) {
      // Because of the wrapping, we need the ->obj
      $einfo = $BrowserHawk->getExtendedBrowserInfo($_req, $_res, $opts->obj);
    }
    else {
      $einfo = $BrowserHawk->getExtendedBrowserInfo($_req, $_res, $opts);
    }
    if (!isset($einfo)) {
      exit();  // The JavaScript has been sent, ready for the second pass
    }
    else {
      if (version_compare(phpversion(), "5.0.0", ">=")) {
        return new Wrap($einfo);
      }
      else {
        return $einfo;
      }
    }
  }

  //ob_end_flush();
?>
