Source for file dpclient.php
Documentation is available at dpclient.php
* Serves as a gateway between the browser and the PHP DutchPIPE server
* Passes the HTTP request to the PHP server along with its environment and user
* variables, and returns the info retrieved from the PHP server back to the
* user's browser. Used to serve pages, and by the AJAX engine in
* dpclient-js.php. It talks to the PHP server using a fast file socket
* DutchPIPE version 0.4; PHP version 5
* LICENSE: This source file is subject to version 1.0 of the DutchPIPE license.
* If you did not receive a copy of the DutchPIPE license, you can obtain one at
* http://dutchpipe.org/license/1_0.txt or by sending a note to
* license@dutchpipe.org, in which case you will be mailed a copy immediately.
* @author Lennert Stock <ls@dutchpipe.org>
* @copyright 2006, 2007 Lennert Stock
* @license http://dutchpipe.org/license/1_0.txt DutchPIPE License
* @version Subversion: $Id: dpclient.php 307 2007-09-01 17:16:09Z ls $
* @link http://dutchpipe.org/manual/package/DutchPIPE
* @see dpserver-ini.php, dpserver.php, dpclient.css
if (!defined('DPSERVER_HOST_URL')) {
require_once(realpath(dirname($_SERVER['SCRIPT_FILENAME']) . '/..')
. '/config/dpserver-ini.php');
* Universe paths used by templates
require_once(DPSERVER_DPUNIVERSE_CONFIG_PATH . 'dpuniverse-ini.php');
* Common functions for templates available to universe objects and dpclient.php
require_once(DPSERVER_LIB_PATH . 'dptemplates.php');
* Provides alternatives to multibyte string functions if not supported
require_once(DPSERVER_LIB_PATH . 'dpmbstring_'
. (!DPSERVER_ENABLE_MBSTRING || !function_exists('mb_strlen')
? 'disabled' : 'enabled') . '.php');
* Contains a message describing the last error, if any
/* Deal with AJAX requests and normal page requests */
if ((!isset ($_GET['ie6']) || $_GET['ie6'] !== 'yes') && isset ($_GET) && (isset ($_GET['ajax']) || isset ($_GET['method']))) {
/* Output XML or '1' to "keep-alive" */
* Talks to the DutchPIPE server, returns response
* @return boolean|string output from the DutchPIPE server, FALSE for error
global $gLastErrorMsg, $header_data;
/* Creates a file socket and connects to it */
if (FALSE === ($socket = socket_create(AF_UNIX, SOCK_STREAM, 0))) {
"socket_create(): unable to create socket [%u]: %s\n"),
"socket_create(): unable to connect [%u]: %s\n"),
/* Creates a TCP/IP socket and connects to it */
"socket_create(): unable to create socket [%u]: %s\n"),
"socket_create(): unable to connect [%u]: %s\n"),
. dp_text('Invalid socket protocol');
/* Talk to the DutchPIPE server and write user variables to it */
if (isset ($_FILES['dpuploadimg'])
&& isset ($_FILES['dpuploadimg']['tmp_name'])) {
@chmod($_FILES['dpuploadimg']['tmp_name'], 0777);
/* Serialize $_SERVER, $_SESSION, ... variables so they can be sent */
$in = serialize(array($_SERVER, $_SESSION, $_COOKIE, $_GET, $_POST,
$in = "<vars>$in</vars>\r\nquit\r\n";
/* Read and process server reply, filter header info given by the server,
put the remainder in $output */
$cookie_set = $remove_guest_cookie = $remove_registered_cookie = FALSE;
foreach ($arroutput as $buf) {
if (!dp_strlen($buf) || isset ($newlocation)) {
&& dp_substr($bufdec, 0, 11) == "Set-Login: ") {
"<header><![CDATA[")) && FALSE !== ($pos2 = dp_strpos($bufdec,
"]]></header>")) && $pos2 > $pos1 + 12) {
$header_data = dp_substr($header_data, $pos1 + 17);
"<cookie><![CDATA[")) && FALSE !== ($pos2 = dp_strpos($bufdec,
"]]></cookie>")) && $pos2 > $pos1 + 12) {
$cookie_data = dp_substr($cookie_data, $pos1 + 17);
if ($cookie_data == 'removeguest') {
$remove_guest_cookie = TRUE;
elseif ($cookie_data == 'removeregistered') {
$remove_registered_cookie = TRUE;
"<location><![CDATA[")) && FALSE !== ($pos2 = dp_strpos($bufdec,
"]]></location>")) && $pos2 > $pos1 + 14) {
$output = "<location><![CDATA[$newlocation]]></location>";
/* Close cocket, return server reply */
if (FALSE === $cookie_set) {
if (FALSE !== $remove_guest_cookie) {
if (FALSE !== $remove_registered_cookie) {
if (isset ($newlocation)) {
if (!isset ($_GET) || !isset ($_GET['ajax'])) {
header("Location: $newlocation");
* Handles AJAX requests from dpclient-js.php
* @param string $output The output from talk2server()
if (FALSE === $output || $output == '1') {
apache_setenv('no-gzip', '1');
elseif (FALSE === $output || $output == '2') {
apache_setenv('no-gzip', '1');
if (isset ($_GET) && isset ($GET['standalone']) && isset ($GET['_seq'])
&& $GET['_seq'] == '0') {
'<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'
. '<dutchpipe>' . $output . '</dutchpipe>');
apache_setenv('no-gzip', '1');
header('Content-Type: text/xml');
echo "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>
<dutchpipe>$output</dutchpipe>\n";
* Sets cookies transmitted with the xml we got from the server
* @param string &$xml XML of the output from talk2server()
foreach ($xml->cookie as $id => $cookie) {
foreach($xml->cookie->attributes() as $attname => $attval) {
$expire = dp_strlen($attval) ? $attval : FALSE;
(!isset ($expire) ? FALSE : $expire), $path);
setcookie($name, $cookie, (!isset ($expire) ? FALSE : $expire),
(!isset ($path) ? '' : $path), $domain);
setcookie($name, $cookie, (!isset ($expire) ? FALSE : $expire),
(!isset ($path) ? '' : $path), (!isset ($domain) ? '' : $domain),
* Handles a normal page request
* @param string $output The output from talk2server()
if (isset ($_GET['ie6']) && 'yes' === $_GET['ie6']) {
/* Otherwise serve the page with the retrieved content in it */
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
. 'standalone="yes" ?><dutchpipe>' . $output . '</dutchpipe>');
$messages = $windows = array();
$body = $dpelements = $scripts = '';
$inputpersistent = $template_file = FALSE;
foreach ($xml->event as $e) {
foreach ($e as $type => $data) {
$dpelements .= $data->asXML();
$dpelements .= $data->asXML();
$dpelements .= $data->asXML();
$dpelements .= $data->asXML();
$dpelements .= $data->asXML();
if (FALSE !== $pos1 && FALSE !== $pos2 && $pos1 < $pos2) {
. dp_substr($tmp, $pos1 + 9, $pos2 - $pos1 - 9)
foreach ($data->attributes() as $a => $b) {
$body .= str_replace(' template="' . (!$template_file ? ''
: $template_file) . '"', '', $data);
$windows[] = '<div class="dpwindow_default" id="dpwindow">'
. $data . '<p align="right"><a href="javascript:'
. 'close_dpwindow()">' . $closetext . '</a></p></div>';
foreach ($data->attributes() as $a => $b) {
if ('persistent' === $a) {
$body = '<h1>' . dp_text('Error fetching page. Invalid page XML.')
$dpelements = " <script type=\"text/javascript\">
function dp_load_xml(text)
if (window.ActiveXObject) {
xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
else if (document.implementation &&
document.implementation.createDocument) {
var parser = new DOMParser();
var xmlDoc=parser.parseFromString(text,'text/xml');
/* alert('Your browser cannot handle this script'); */
function dp_load_elements()
var content = '<?xml version=\"1.0\"?><dutchpipe>"
. "<event count=\"-1\" time=\"-1\">" . addslashes($dpelements)
. "</event></dutchpipe>'; handle_response(dp_load_xml(content));
$messages_style = !sizeof($messages) ? ''
: ' style="display: block; padding-top: 12px"';
$windows = implode("\n", $windows);
$messages = implode("\n", $messages);
$subtemplates = dp_get_subtemplates(array('input', 'input_say'),
include($subtemplates['input']);
if ('always' == $inputpersistent) {
include($subtemplates['input_say']);
if ('always' == $inputpersistent) {
/* Otherwise serve the page with the retrieved content in it */
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
require_once(!$template_file
|