From 1fbb260ad3c9424cc6468adda7b42fef8680d1ad Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Fri, 29 Aug 2008 16:05:04 +0000 Subject: [PATCH] not used any more --- phpgwapi/inc/class.http_dav_client.inc.php | 1119 -------------------- phpgwapi/inc/class.net_http_client.inc.php | 869 --------------- 2 files changed, 1988 deletions(-) delete mode 100644 phpgwapi/inc/class.http_dav_client.inc.php delete mode 100644 phpgwapi/inc/class.net_http_client.inc.php diff --git a/phpgwapi/inc/class.http_dav_client.inc.php b/phpgwapi/inc/class.http_dav_client.inc.php deleted file mode 100644 index 72eb2c4aa0..0000000000 --- a/phpgwapi/inc/class.http_dav_client.inc.php +++ /dev/null @@ -1,1119 +0,0 @@ - * - * Provides methods for manipulating an RFC 2518 DAV repository * - * Copyright (C) 2002 Zeald Ltd * - * -------------------------------------------------------------------------* - * This library is part of the eGroupWare API * - * http://www.egroupware.org/api * - * ------------------------------------------------------------------------ * - * This library is free software; you can redistribute it and/or modify it * - * under the terms of the GNU Lesser General Public License as published by * - * the Free Software Foundation; either version 2.1 of the License, * - * or any later version. * - * This library is distributed in the hope that it will be useful, but * - * WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * - * See the GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License * - * along with this library; if not, write to the Free Software Foundation, * - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - \**************************************************************************/ - - /* $Id$ */ - - /*At the moment much of this is simply a wrapper around the NET_HTTP_Client class, - with some other methods for parsing the returned XML etc - Ideally this will eventually use groupware's inbuilt HTTP class - */ - - define ('DEBUG_DAV_CLIENT', 0); - define ('DEBUG_DAV_XML', 0); - define ('DEBUG_CACHE', 0); - - -############################################################## -# 'Private' classes - these are only used internally and should -# not be used by external code -############################################################## - - /* - PHP STILL doesnt have any sort of stable DOM parser. So lets make our - own XML parser, that parses XML into a tree of arrays (I know, it could do - something resembling DOM, but it doesnt!) - */ - class xml_tree_parser - { - var $namespaces; - var $current_element; - var $num = 1; - var $tree = NULL; - - /* - This is the only end-user function in the class. Call parse with an XML string, and - you will get back the tree of 'element' arrays - */ - function parse($xml_string) - { - $this->xml_parser = xml_parser_create(); - xml_set_element_handler($this->xml_parser,array(&$this,"start_element"),array(&$this,"end_element")); - xml_set_character_data_handler($this->xml_parser,array(&$this,"parse_data")); - - $this->parser_result=array(); - $this->xml = $xml_string; - xml_parse($this->xml_parser,$xml_string); - xml_parser_free($this->xml_parser); - if (DEBUG_DAV_XML) - { - echo '
'.htmlentities($xml_string).'
'; - echo 'parsed to:' ; $this->print_tree(); - } - return $this->tree; - } - - //a useful function for debug output - will print the tree after parsing - function print_tree($element=NULL, $prefix='|', $processed=array()) - { - - if ($processed[$element['id']]) - { - echo '***RECURSION!!***
'; - die(); - } - else - { - $processed[$element['id']] = true; - } - - if ($element == NULL) - { - $element = $this->tree; - } - echo $prefix.$element['namespace'].':'.$element['name'].' '.$element['start'].'->'.$element['end'].'
'; - $prefix .= '-->'; - if ($element['data']) - { - echo $prefix.$element['data'].'
'; - } - - foreach ($element['children'] as $id=>$child) - { - $this->print_tree($child, $prefix, &$processed); - } - - } - - //called by the xml parser at the start of an element, it creates that elements node in the tree - function start_element($parser,$name,$attr) - { - - if (preg_match('/(.*):(.*)/', $name, $matches)) - { - $ns = $this->namespaces[$matches[1]]; - $element = $matches[2]; - } - else - { - $element = $name; - } - - if ($this->tree == NULL) - { - $this->tree = array( - 'namespace'=>$ns, - 'name' => $element, - 'attributes' => $attr, - 'data' => '', - 'children' => array(), - 'parent' => NULL, - 'type' => 'xml_element', - 'id' => $this->num - ); - $this->current_element = &$this->tree; - } - else - { - $parent = &$this->current_element; - $parent['children'][$this->num]=array( - 'namespace'=>$ns, - 'name' => $element, - 'attributes' => $attr, - 'data' => '', - 'children' => array(), - 'parent' => &$parent, - 'type' => 'xml_element', - 'id' => $this->num - ); - $this->current_element = &$parent['children'][$this->num]; - } - $this->num++; - $this->current_element['start'] = xml_get_current_byte_index($parser); - foreach ($attr as $name => $value) - { - if (ereg('^XMLNS:(.*)', $name, $matches) ) - { - $this->namespaces[$matches[1]] = $value; - } - } - } - - //at the end of an element, stores the start and end positions in the xml stream, and moves up the tree - function end_element($parser,$name) - { - $curr = xml_get_current_byte_index($parser); - $this->current_element['end'] =strpos($this->xml, '>', $curr); - $this->current_element = &$this->current_element['parent']; - - } - - //if there is a CDATA element, puts it into the parent elements node - function parse_data($parser,$data) - { - $this->current_element['data']=$data; - } - - } - - /*This class uses a bunch of recursive functions to process the DAV XML tree - digging out the relevent information and putting it into an array - */ - class dav_processor - { - function dav_processor($xml_string) - { - $this->xml = $xml_string; - $this->dav_parser = new xml_tree_parser(); - $this->tree = $this->dav_parser->parse($xml_string); - - } - - function process_tree(&$element, &$result_array) - { - - //This lets us mark a node as 'done' and provides protection against infinite loops - if ($this->processed[$element['id']]) - { - return $result_array; - } - else - { - $this->processed[$element['id']] = true; - } - - if ( $element['namespace'] == 'DAV:') - { - if ($element['name'] == 'RESPONSE') - { - $result = array( - 'size' => 0, - 'getcontenttype' => 'application/octet-stream', - 'is_dir' => 0 - ); - foreach ($element['children'] as $id=>$child) - { - $this->process_properties($child, $result); - } - $result_array[$result['full_name']] = $result; - - } - } - // ->recursion - foreach ($element['children'] as $id=>$child) - { - $this->process_tree($child, $result_array); - } - return $result_array; - } - - function process_properties($element, &$result_array) - { - if ($this->processed[$element['id']]) - { - return $result_array; - } - else - { - $this->processed[$element['id']] = true; - } - - if ( $element['namespace'] == 'DAV:') - { - switch ($element['name']) - { - case 'HREF': - $string = $element['data']; - $idx=strrpos($string,SEP); - if($idx && $idx==strlen($string)-1) - { - $this->current_ref=substr($string,0,$idx); - } - else - { - $this->current_ref=$string; - } - $result_array['name']=basename($string); - $result_array['directory']=dirname($string); - $result_array['full_name'] = $this->current_ref; - break; - case 'SUPPORTEDLOCK': - if (count($element['children'])) //There are active locks - { - $result_array['supported_locks'] = array(); - foreach ($element['children'] as $id=>$child) - { - $this->process_properties($child, $result_array['supported_locks']); - } - } - break; - case 'LOCKDISCOVERY': - if (count($element['children'])) //There are active locks - { - $result_array['locks'] = array(); - foreach ($element['children'] as $id=>$child) - { - $this->process_properties($child, $result_array['locks']); - } - } - break; - case 'LOCKENTRY': - if (count($element['children'])) - { - $result_array[$element['id']] = array(); - foreach ($element['children'] as $id=>$child) - { - $this->process_properties($child, $result_array[$element['id']] ); - } - } - break; - case 'ACTIVELOCK': - if (count($element['children'])) - { - $result_array[$element['id']] = array(); - foreach ($element['children'] as $id=>$child) - { - $this->process_properties($child, $result_array[$element['id']] ); - } - } - break; - case 'OWNER': - $result_array['owner'] = array(); - - foreach ($element['children'] as $child) - { - $this->process_verbatim($child, &$result_array['owner'][]); - } - - //print_r($element);die(); - //die(); - $result_array['owner_xml'] = substr($this->xml, $element['start'], $element['end']-$element['start']+1); - return $result_array; //No need to process this branch further - break; - case 'LOCKTOKEN': - if (count($element['children'])) - { - - foreach ($element['children'] as $id=>$child) - { - $this->process_properties($child, $tmp_result , $processed); - $result_array['lock_tokens'][$tmp_result['full_name']] = $tmp_result; - } - } - break; - case 'LOCKTYPE': - $child = end($element['children']); - if ($child) - { - $this->processed[$child['id']] = true; - $result_array['locktype'] = $child['name']; - } - break; - case 'LOCKSCOPE': - $child = end($element['children']); - if ($child) - { - $this->processed[$child['id']] = true; - $result_array['lockscope'] = $child['name']; - } - break; - default: - if (trim($element['data'])) - { - $result_array[strtolower($element['name'])] = $element['data']; - } - } - } - else - { - if (trim($element['data'])) - { - $result_array[strtolower($element['name'])] = $element['data']; - } - } - - foreach ($element['children'] as $id=>$child) - { - $this->process_properties($child, $result_array); - } - - return $result_array; - } - - function process_verbatim($element, &$result_array) - { - if ($this->processed[$element['id']]) - { - return $result_array; - } - else - { - $this->processed[$element['id']] = true; - } - - foreach ( $element as $key => $value) - { - //The parent link is death to naive programmers (eg me) :) - if (!( $key == 'children' || $key == 'parent') ) - { - $result_array[$key] = $value; - } - } - $result_array['children'] = array(); - foreach ($element['children'] as $id=>$child) - { - echo 'processing child:'; - $this->process_verbatim($child, $result_array['children']); - } - return $result_array; - } - } - -##################################################### -#This is the actual public interface of this class -##################################################### - class http_dav_client - { - var $attributes=array(); - var $vfs_property_map = array(); - var $cached_props = array(); - function http_dav_client() - { - $this->http_client = CreateObject('phpgwapi.net_http_client'); - $this->set_debug(0); - } - - //TODO: Get rid of this - //A quick, temporary debug output function - function debug($info) { - - if (DEBUG_DAV_CLIENT) - { - echo ' http_dav_client debug: '; - if (is_array($info)) - { - print_r($info); - } - else - { - echo $info; - } - echo '
'; - } - } - /*! - @function glue_url - @abstract glues a parsed url (ie parsed using PHP's parse_url) back - together - @param $url The parsed url (its an array) - */ - - function glue_url ($url){ - if (!is_array($url)) - { - return false; - } - // scheme - $uri = (!empty($url['scheme'])) ? $url['scheme'].'://' : ''; - // user & pass - if (!empty($url['user'])) - { - $uri .= $url['user']; - if (!empty($url['pass'])) - { - $uri .=':'.$url['pass']; - } - $uri .='@'; - } - // host - $uri .= $url['host']; - // port - $port = (!empty($url['port'])) ? ':'.$url['port'] : ''; - $uri .= $port; - // path - $uri .= $url['path']; - // fragment or query - if (isset($url['fragment'])) - { - $uri .= '#'.$url['fragment']; - } elseif (isset($url['query'])) - { - $uri .= '?'.$url['query']; - } - return $uri; - } - - /*! - @function encodeurl - @abstract encodes a url from its "display name" to something the dav server will accept - @param uri The unencoded uri - @discussion - Deals with "url"s which may contain spaces and other unsavoury characters, - by using appropriate %20s - */ - function encodeurl($uri) - { - $parsed_uri = parse_url($uri); - if (empty($parsed_uri['scheme'])) - { - $path = $uri; - } - else - { - $path = $parsed_uri['path']; - } - $fixed_array = array(); - foreach (explode('/', $path) as $name) - { - $fixed_array[] = rawurlencode($name); - } - $fixed_path = implode('/', $fixed_array); - if (!empty($parsed_uri['scheme'])) - { - $parsed_uri['path'] = $fixed_path; - $newuri = $this->glue_url($parsed_uri); - } - else - { - $newuri = $fixed_path; - } - return $newuri; - - } - /*! - @function decodeurl - @abstract decodes a url to its "display name" - @param uri The encoded uri - @discussion - Deals with "url"s which may contain spaces and other unsavoury characters, - by using appropriate %20s - */ - function decodeurl($uri) - { - $parsed_uri = parse_url($uri); - if (empty($parsed_uri['scheme'])) - { - $path = $uri; - } - else - { - $path = $parsed_uri['path']; - } - $fixed_array = array(); - foreach (explode('/', $path) as $name) - { - $fixed_array[] = rawurldecode($name); - } - $fixed_path = implode('/', $fixed_array); - if (!empty($parsed_uri['scheme'])) - { - $parsed_uri['path'] = $fixed_path; - $newuri = $this->glue_url($parsed_uri); - } - else - { - $newuri = $fixed_path; - } - return $newuri; - - } - /*! - @function set_attributes - @abstract Sets the "attribute map" - @param attributes Attributes to extract "as-is" from the DAV properties - @param dav_map A mapping of dav_property_name => attribute_name for attributes - with different names in DAV and the desired name space. - @discussion - This is mainly for use by VFS, where the VFS attributes (eg size) differ - from the corresponding DAV ones ("getcontentlength") - */ - function set_attributes($attributes, $dav_map) - { - $this->vfs_property_map = $dav_map; - $this->attributes = $attributes; - } - - /*! - @function set_credentials - @abstract Sets authentication credentials for HTTP AUTH - @param username The username to connect with - @param password The password to connect with - @discussion - The only supported authentication type is "basic" - */ - function set_credentials( $username, $password ) - { - $this->http_client->setCredentials($username, $password ); - } - - /*! - @function connect - @abstract connects to the server - @param dav_host The host to connect to - @param dav_port The port to connect to - @discussion - If the server requires authentication you will need to set credentials - with set_credentials first - */ - - function connect($dav_host,$dav_port) - { - $this->dav_host = $dav_host; - $this->dav_port = $dav_port; - $this->http_client->addHeader('Host',$this->dav_host); - $this->http_client->addHeader('Connection','close'); - //$this->http_client->addHeader('transfer-encoding','identity'); - // $this->http_client->addHeader('Connection','keep-alive'); - // $this->http_client->addHeader('Keep-Alive','timeout=20, state="Accept,Accept-Language"'); - $this->http_client->addHeader('Accept-Encoding','chunked'); - $this->http_client->setProtocolVersion( '1.1' ); - $this->http_client->addHeader( 'user-agent', 'Mozilla/5.0 (compatible; eGroupWare dav_client/1; Linux)'); - return $this->http_client->Connect($dav_host,$dav_port); - } - function set_debug($debug) - { - $this->http_client->setDebug($debug); - } - - /*! - @function disconnect - @abstract disconnect from the server - @discussion - When doing HTTP 1.1 we frequently close/reopen the connection - anyway, so this function needs to be called after any other DAV calls - (since if they find the connection closed, they just reopen it) - */ - - function disconnect() - { - $this->http_client->Disconnect(); - } - - /*! - @function get_properties - @abstract a high-level method of getting DAV properties - @param url The URL to get properties for - @param scope the 'depth' to recuse subdirectories (default 1) - @param sorted whether we should sort the rsulting array (default True) - @result array of file->property arra - @discussion - This function performs all the necessary XML parsing etc to convert DAV properties (ie XML nodes) - into associative arrays of properties - including doing mappings - from DAV property names to any desired property name format (eg the VFS one) - This is controlled by the attribute arrays set in the set_attributes function. - */ - function get_properties($url,$scope=1){ - $request_id = $url.'//'.$scope.'//'.$sorted; //A unique id for this request (for caching) - if ($this->cached_props[$request_id]) - { -if (DEBUG_CACHE) echo'Cache hit : cache id:'.$request_id; - return $this->cached_props[$request_id]; - } - else if (! $sorted && $this->cached_props[$url.'//'.$scope.'//1']) - { -if (DEBUG_CACHE) echo ' Cache hit : cache id: '.$request_id; - return $this->cached_props[$url.'//'.$scope.'//1']; - } -if (DEBUG_CACHE) -{ - echo ' Cache miss : cache id: '.$request_id; -/* echo " cache:
";
-	print_r($this->cached_props);
-	echo '
';*/ -} - - - if($this->propfind($url,$scope) != 207) - { - if($this->propfind($url.'/',$scope) != 207) - { - return array(); - } - } - $xml_result=$this->http_client->getBody(); - $result_array = array(); - $dav_processor = new dav_processor($xml_result); - $tmp_list = $dav_processor->process_tree($dav_processor->tree, $result_array); - - foreach($tmp_list as $name=>$item) { - $fixed_name = $this->decodeurl($name); - $newitem = $item; - $newitem['is_dir']= ($item['getcontenttype'] =='httpd/unix-directory' ? 1 : 0); - $item['directory'] = $this->decodeurl($item['directory']); - //Since above we sawed off the protocol and host portions of the url, lets readd them. - if (strlen($item['directory'])) { - $path = $item['directory']; - $host = $this->dav_host; - $newitem['directory'] = $host.$path; - } - - //Get any extra properties that may share the vfs name - foreach ($this->attributes as $num=>$vfs_name) - { - if ($item[$vfs_name]) - { - $newitem[$vfs_name] = $item[$vfs_name]; - } - } - - //Map some DAV properties onto VFS ones. - foreach ($this->vfs_property_map as $dav_name=>$vfs_name) - { - if ($item[$dav_name]) - { - $newitem[$vfs_name] = $item[$dav_name]; - } - } - - if ($newitem['is_dir'] == 1) - { - $newitem['mime_type']='Directory'; - } - - $this->debug('

properties:
'); - $this->debug($newitem); - $newitem['name'] = $this->decodeurl($newitem['name']); - $result[$fixed_name]=$newitem; - if ($newitem['is_dir']==1) - { - $this->cached_props[$name.'//0//1'] = array($fixed_name=>$newitem); - } - else - { - $this->cached_props[$name.'//1//1'] = array($fixed_name=>$newitem); - } - } - if ($sorted) - { - ksort($result); - } - $this->cached_props[$request_id] = $result; - return $result; - } - - function get($uri) - { - $uri = $this->encodeurl($uri); - return $this->http_client->Get($uri); - } - - /*! - @function get_body - @abstract return the response body - @result string body content - @discussion - invoke it after a Get() call for instance, to retrieve the response - */ - function get_body() - { - return $this->http_client->getBody(); - } - - /*! - @function get_headers - @abstract return the response headers - @result array headers received from server in the form headername => value - @discussion - to be called after a Get() or Head() call - */ - function get_headers() - { - return $this->http_client->getHeaders(); - } - - /*! - @function copy - @abstract PUT is the method to sending a file on the server. - @param uri the location of the file on the server. dont forget the heading "/" - @param data the content of the file. binary content accepted - @result string response status code 201 (Created) if ok - */ - function put($uri, $data, $token='') - { - $uri = $this->encodeurl($uri); -if (DEBUG_CACHE) echo 'cache cleared'; - if (strlen($token)) - { - $this->http_client->addHeader('If', '<'.$uri.'>'.' (<'.$token.'>)'); - } - - $this->cached_props = array(); - $result = $this->http_client->Put($uri, $data); - $this->http_client->removeHeader('If'); - return $result; - } - - /*! - @function copy - @abstract Copy a file -allready on the server- into a new location - @param srcUri the current file location on the server. dont forget the heading "/" - @param destUri the destination location on the server. this is *not* a full URL - @param overwrite boolean - true to overwrite an existing destination - overwrite by default - @result Returns the HTTP status code - @discussion - returns response status code 204 (Unchanged) if ok - */ - function copy( $srcUri, $destUri, $overwrite=true, $scope=0, $token='') - { - $srcUri = $this->encodeurl($srcUri); - $destUri = $this->encodeurl($destUri); -if (DEBUG_CACHE) echo 'cache cleared'; - if (strlen($token)) - { - $this->http_client->addHeader('If', '<'.$uri.'>'.' (<'.$token.'>)'); - } - $this->cached_props = array(); - $result = $this->http_client->Copy( $srcUri, $destUri, $overwrite, $scope); - $this->http_client->removeHeader('If'); - return $result; - } - - /*! - @function move - @abstract Moves a WEBDAV resource on the server - @param srcUri the current file location on the server. dont forget the heading "/" - @param destUri the destination location on the server. this is *not* a full URL - @param overwrite boolean - true to overwrite an existing destination (default is yes) - @result Returns the HTTP status code - @discussion - returns response status code 204 (Unchanged) if ok - */ - function move( $srcUri, $destUri, $overwrite=true, $scope=0, $token='' ) - { - $srcUri = $this->encodeurl($srcUri); - $destUri = $this->encodeurl($destUri); -if (DEBUG_CACHE) echo 'cache cleared'; - if (strlen($token)) - { - $this->http_client->addHeader('If', '<'.$uri.'>'.' (<'.$token.'>)'); - } - $this->cached_props = array(); - $result = $this->http_client->Move( $srcUri, $destUri, $overwrite, $scope); - $this->http_client->removeHeader('If'); - return $result; - } - - /*! - @function delete - @abstract Deletes a WEBDAV resource - @param uri The URI we are deleting - @result Returns the HTTP status code - @discussion - returns response status code 204 (Unchanged) if ok - */ - function delete( $uri, $scope=0, $token='') - { - $uri = $this->encodeurl($uri); -if (DEBUG_CACHE) echo 'cache cleared'; - if (strlen($token)) - { - $this->http_client->addHeader('If', '<'.$uri.'>'.' (<'.$token.'>)'); - } - - $this->cached_props = array(); - $result = $this->http_client->Delete( $uri, $scope); - $this->http_client->removeHeader('If'); - return $result; - } - - /*! - @function mkcol - @abstract Creates a WEBDAV collection (AKA a directory) - @param uri The URI to create - @result Returns the HTTP status code - */ - function mkcol( $uri, $token='' ) - { - $uri = $this->encodeurl($uri); -if (DEBUG_CACHE) echo 'cache cleared'; - if (strlen($token)) - { - $this->http_client->addHeader('If', '<'.$uri.'>'.' (<'.$token.'>)'); - } - $this->cached_props = array(); - return $this->http_client->MkCol( $uri ); - $this->http_client->removeHeader('If'); - } - - /*! - @function propfind - @abstract Queries WEBDAV properties - @param uri uri of resource whose properties we are changing - @param scope Specifies how "deep" to search (0=just this file/dir 1=subfiles/dirs etc) - @result Returns the HTTP status code - @discussion - to get the result XML call get_body() - */ - function propfind( $uri, $scope=0 ) - { - $uri = $this->encodeurl($uri); - return $this->http_client->PropFind( $uri, $scope); - } - /*! - @function proppatch - @abstract Sets DAV properties - @param uri uri of resource whose properties we are changing - @param attributes An array of attributes and values. - @param namespaces Extra namespace definitions that apply to the properties - @result Returns the HTTP status code - @discussion - To make DAV properties useful it helps to use a well established XML dialect - such as the "Dublin Core" - - */ - function proppatch($uri, $attributes, $namespaces='', $token='') - { - $uri = $this->encodeurl($uri); -if (DEBUG_CACHE) echo 'cache cleared'; - if (strlen($token)) - { - $this->http_client->addHeader('If', '<'.$uri.'>'.' (<'.$token.'>)'); - } - $this->cached_props = array(); - //Begin evil nastiness - $davxml = ' - $value) - { - $davxml .= ' - - - <'.$name.'>'.utf8_encode(htmlspecialchars($value)).' - - -'; - } - $davxml .= ' -'; - - if (DEBUG_DAV_XML) { - echo 'send
'.htmlentities($davxml).'
'; - } - $this->http_client->requestBody = $davxml; - if( $this->http_client->sendCommand( 'PROPPATCH '.$uri.' HTTP/1.1' ) ) - { - $this->http_client->processReply(); - } - - if (DEBUG_DAV_XML) { - echo 'Recieve
'.htmlentities($this->http_client->getBody()).'
'; - } - $this->http_client->removeHeader('If'); - return $this->http_client->reply; - } - - /*! - @function unlock - @abstract unlocks a locked resource on the DAV server - @param uri uri of the resource we are unlocking - @param a 'token' for the lock (to get the token, do a propfind) - @result true if successfull - @discussion - Not all DAV servers support locking (its in the RFC, but many common - DAV servers only implement "DAV class 1" (no locking) - */ - - function unlock($uri, $token) - { - $uri = $this->encodeurl($uri); -if (DEBUG_CACHE) echo 'cache cleared'; - $this->cached_props = array(); - $this->http_client->addHeader('Lock-Token', '<'.$token.'>'); - $this->http_client->sendCommand( 'UNLOCK '.$uri.' HTTP/1.1'); - $this->http_client->removeHeader('Lock-Token'); - $this->http_client->processReply(); - if ( $this->http_client->reply == '204') - { - return true; - } - else - { - $headers = $this->http_client->getHeaders(); - echo $this->http_client->getBody(); - if ($headers['Content-Type'] == 'text/html') - { - echo $this->http_client->getBody(); - die(); - } - else - { - return false; - } - } - } - - /*! - @function lock - @abstract locks a resource on the DAV server - @param uri uri of the resource we are locking - @param owner the 'owner' information for the lock (purely informative) - @param depth the depth to which we lock collections - @result true if successfull - @discussion - Not all DAV servers support locking (its in the RFC, but many common - DAV servers only implement "DAV class 1" (no locking) - */ - function lock($uri, $owner, $depth=0, $timeout='infinity') - { - $uri = $this->encodeurl($uri); -if (DEBUG_CACHE) echo 'cache cleared'; - $this->cached_props = array(); - $body = " - -\n - $owner -\n"; - - $this->http_client->requestBody = utf8_encode( $body ); - $this->http_client->addHeader('Depth', $depth); - if (! (strtolower(trim($timeout)) == 'infinite')) - { - $timeout = 'Second-'.$timeout; - } - $this->http_client->addHeader('Timeout', $timeout); - - if( $this->http_client->sendCommand( "LOCK $uri HTTP/1.1" ) ) - $this->http_client->processReply(); - $this->http_client->removeHeader('timeout'); - if ( $this->http_client->reply == '200') - { - return true; - } - else - { - $headers = $this->http_client->getHeaders(); - echo $this->http_client->getBody(); - return false; - - } - - } - /*! - @function options - @abstract determines the optional HTTP features supported by a server - @param uri uri of the resource we are seeking options for (or * for the whole server) - @result Returns an array of option values - @discussion - Interesting options include "ACCESS" (whether you can read a file) and - DAV (DAV features) - - */ - function options($uri) - { - $uri = $this->encodeurl($uri); - if( $this->http_client->sendCommand( 'OPTIONS '.$uri.' HTTP/1.1' ) == '200' ) - { - $this->http_client->processReply(); - $headers = $this->http_client->getHeaders(); - return $headers; - } - else - { - return False; - } - } - /*! - @function dav_features - @abstract determines the features of a DAV server - @param uri uri of resource whose properties we are changing - @result Returns an array of option values - @discussion - Likely return codes include NULL (this isnt a dav server!), 1 - (This is a dav server, supporting all standard DAV features except locking) - 2, (additionally supports locking (should also return 1)) and - 'version-control' (this server supports versioning extensions for this resource) - */ - function dav_features($uri) - { - $uri = $this->encodeurl($uri); - $options = $this->options($uri); - $dav_options = $options['DAV']; - if ($dav_options) - { - $features=explode(',', $dav_options); - } - else - { - $features = NULL; - } - return $features; - } -/************************************************************** - RFC 3253 DeltaV versioning extensions - ************************************************************** - These are 100% untested, and almost certainly dont work yet... - eventually they will be made to work with subversion... - */ - - /*! - @function report - @abstract Report is a kind of extended PROPFIND - it queries properties accros versions etc - @param uri uri of resource whose properties we are changing - @param report the type of report desired eg DAV:version-tree, DAV:expand-property etc (see http://greenbytes.de/tech/webdav/rfc3253.html#METHOD_REPORT) - @param namespace any extra XML namespaces needed for the specified properties - @result Returns an array of option values - @discussion - From the relevent RFC: - "A REPORT request is an extensible mechanism for obtaining information about - a resource. Unlike a resource property, which has a single value, the value - of a report can depend on additional information specified in the REPORT - request body and in the REPORT request headers." - */ - function report($uri, $report, $properties, $namespaces='') - { - $uri = $this->encodeurl($uri); - $davxml = ' -\n'; - } - $davxml .= '\t\n'; - if (DEBUG_DAV_XML) { - echo 'send
'.htmlentities($davxml).'
'; - } - $this->http_client->requestBody = $davxml; - if( $this->http_client->sendCommand( 'REPORT '.$uri.' HTTP/1.1' ) ) - { - $this->http_client->processReply(); - } - - if (DEBUG_DAV_XML) { - echo 'Recieve
'.htmlentities($this->http_client->getBody()).'
'; - } - return $this->http_client->reply; - } - - } - diff --git a/phpgwapi/inc/class.net_http_client.inc.php b/phpgwapi/inc/class.net_http_client.inc.php deleted file mode 100644 index c8e8a3df96..0000000000 --- a/phpgwapi/inc/class.net_http_client.inc.php +++ /dev/null @@ -1,869 +0,0 @@ - * - * ------------------------------------------------------------------------ * - * This library is not part of eGroupWare, but is used by eGroupWare. * - * ------------------------------------------------------------------------ * - * This program is free software; you can redistribute it and/or modify it * - * under the terms of the GNU General Public License as published by the * - * Free Software Foundation; either version 2 of the License, or (at your * - * option) any later version. * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the Free Software * - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - \**************************************************************************/ - - -/* - - net_http_client class - -@DESCRIPTION - - HTTP Client component - suppots methods HEAD, GET, POST - 1.0 and 1.1 compliant - WebDAV methods tested against Apache/mod_dav - Documentation @ http://lwest.free.fr/doc/php/lib/net_http_client-en.html - -@SYNOPSIS - - include "Net/HTTP/Client.php"; - - $http = new net_http_client(); - $http->connect( "localhost", 80 ) or die( "connect problem" ); - $status = $http->get( "/index.html" ); - if( $status != 200 ) - die( "Problem : " . $http->getStatusMessage() . "\n" ); - $http->disconnect(); - - - -@CHANGES - 0.1 initial version - 0.2 documentation completed - + getHeaders(), getBody() - o Post(), Connect() - 0.3 DAV enhancements: - + Put() method - 0.4 continued DAV support - + Delete(), Move(), MkCol(), Propfind() methods - o added url property, remove host and port properties - o Connect, net_http_client (use of this.url) - o processBody() : use non-blocking to fix a socket pblm - 0.5 debug support - + setDebug() - + debug levels definitions (DBG*) - 0.6 + Lock() method - + setCredentials() method and fix - thanks Thomas Olsen - + support for Get( full_url ) - o fix POST call (duplicate content-length) - thanks to Javier Sixto - 0.7 + OPTIONS method support - + addCookie and removeCookies methods - o fix the "0" problem - o undeifned variable warning fixed - - -@VERSION - 0.7 - -@INFORMATIONS - - Compatibility : PHP 4 >= 4.0b4 - created : May 2001 - LastModified : Sep 2002 - - -@AUTHOR - Leo West - -@TODO - remaining WebDAV methods: UNLOCK PROPPATCH - - -*/ - - -/// debug levels , use it as Client::setDebug( DBGSOCK & DBGTRACE ) -define( "DBGTRACE", 1 ); // to debug methods calls -define( "DBGINDATA", 2 ); // to debug data received -define( "DBGOUTDATA", 4 ); // to debug data sent -define( "DBGLOW", 8 ); // to debug low-level (usually internal) methods -define( "DBGSOCK", 16 ); // to debug socket-level code - -/// internal errors -define( "ECONNECTION", -1 ); // connection failed -define( "EBADRESPONSE", -2 ); // response status line is not http compliant - -define( "CRLF", "\r\n" ); - - -class net_http_client -{ - - // @private - /// array containg server URL, similar to array returned by parseurl() - var $url; - /// server response code eg. "304" - var $reply; - /// server response line eg. "200 OK" - var $replyString; - /// HTPP protocol version used - var $protocolVersion = "1.0"; - /// internal buffers - var $requestHeaders, $requestBody; - /// TCP socket identifier - var $socket = false; - /// proxy informations - var $useProxy = false; - var $proxyHost, $proxyPort; - /// debugging flag - var $debug = 0; - - /** - * net_http_client - * constructor - * Note : when host and port are defined, the connection is immediate - * @seeAlso connect - **/ - function net_http_client( $host= NULL, $port= NULL ) - { - if( $this->debug & DBGTRACE ) echo "net_http_client( $host, $port )\n"; - - if( $host != NULL ) { - $this->connect( $host, $port ); - } - } - - /** - * turn on debug messages - * @param level a combinaison of debug flags - * @see debug flags ( DBG..) defined at top of file - **/ - function setDebug( $level ) - { - if( $this->debug & DBGTRACE ) echo "setDebug( $level )\n"; - $this->debug = $level; - } - - - /** - * turn on proxy support - * @param proxyHost proxy host address eg "proxy.mycorp.com" - * @param proxyPort proxy port usually 80 or 8080 - **/ - function setProxy( $proxyHost, $proxyPort ) - { - if( $this->debug & DBGTRACE ) echo "setProxy( $proxyHost, $proxyPort )\n"; - $this->useProxy = true; - $this->proxyHost = $proxyHost; - $this->proxyPort = $proxyPort; - } - - - /** - * setProtocolVersion - * define the HTTP protocol version to use - * @param version string the version number with one decimal: "0.9", "1.0", "1.1" - * when using 1.1, you MUST set the mandatory headers "Host" - * @return boolean false if the version number is bad, true if ok - **/ - function setProtocolVersion( $version ) - { - if( $this->debug & DBGTRACE ) echo "setProtocolVersion( $version )\n"; - - if( $version > 0 and $version <= 1.1 ) { - $this->protocolVersion = $version; - return true; - } else { - return false; - } - } - - /** - * set a username and password to access a protected resource - * Only "Basic" authentication scheme is supported yet - * @param username string - identifier - * @param password string - clear password - **/ - function setCredentials( $username, $password ) - { - $hdrvalue = base64_encode( "$username:$password" ); - $this->addHeader( "Authorization", "Basic $hdrvalue" ); - } - - /** - * define a set of HTTP headers to be sent to the server - * header names are lowercased to avoid duplicated headers - * @param headers hash array containing the headers as headerName => headerValue pairs - **/ - function setHeaders( $headers ) - { - if( $this->debug & DBGTRACE ) echo "setHeaders( $headers ) \n"; - if( is_array( $headers )) { - foreach( $headers as $name => $value ) { - $this->requestHeaders[$name] = $value; - } - } - } - - /** - * addHeader - * set a unique request header - * @param headerName the header name - * @param headerValue the header value, ( unencoded) - **/ - function addHeader( $headerName, $headerValue ) - { - if( $this->debug & DBGTRACE ) echo "addHeader( $headerName, $headerValue )\n"; - $this->requestHeaders[$headerName] = $headerValue; - } - - /** - * removeHeader - * unset a request header - * @param headerName the header name - **/ - function removeHeader( $headerName ) - { - if( $this->debug & DBGTRACE ) echo "removeHeader( $headerName) \n"; - unset( $this->requestHeaders[$headerName] ); - } - - /** - * addCookie - * set a session cookie, that will be used in the next requests. - * this is a hack as cookie are usually set by the server, but you may need it - * it is your responsabilty to unset the cookie if you request another host - * to keep a session on the server - * @param string the name of the cookie - * @param string the value for the cookie - **/ - function addCookie( $cookiename, $cookievalue ) - { - if( $this->debug & DBGTRACE ) echo "addCookie( $cookiename, $cookievalue ) \n"; - $cookie = $cookiename . "=" . $cookievalue; - $this->requestHeaders["Cookie"] = $cookie; - } - - /** - * removeCookie - * unset cookies currently in use - **/ - function removeCookies() - { - if( $this->debug & DBGTRACE ) echo "removeCookies() \n"; - unset( $this->requestHeaders["Cookie"] ); - } - - /** - * Connect - * open the connection to the server - * @param host string server address (or IP) - * @param port string server listening port - defaults to 80 - * @return boolean false is connection failed, true otherwise - **/ - function Connect( $host, $port = NULL ) - { - if( $this->debug & DBGTRACE ) echo "Connect( $host, $port ) \n"; - - $this->url['scheme'] = "http"; - $this->url['host'] = $host; - if( $port != NULL ) - $this->url['port'] = $port; - return true; - } - - /** - * Disconnect - * close the connection to the server - **/ - function Disconnect() - { - if( $this->debug & DBGTRACE ) echo "Disconnect()\n"; - if( $this->socket ) - fclose( $this->socket ); - } - - /** - * head - * issue a HEAD request - * @param uri string URI of the document - * @return string response status code (200 if ok) - * @seeAlso getHeaders() - **/ - function Head( $uri ) - { - if( $this->debug & DBGTRACE ) echo "Head( $uri )\n"; - $this->responseHeaders = $this->responseBody = ""; - $uri = $this->makeUri( $uri ); - if( $this->sendCommand( "HEAD $uri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - return $this->reply; - } - - - /** - * get - * issue a GET http request - * @param uri URI (path on server) or full URL of the document - * @return string response status code (200 if ok) - * @seeAlso getHeaders(), getBody() - **/ - function Get( $url ) - { - if( $this->debug & DBGTRACE ) echo "Get( $url )\n"; - $this->responseHeaders = $this->responseBody = ""; - $uri = $this->makeUri( $url ); - - if( $this->sendCommand( "GET $uri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - return $this->reply; - } - - /** - * Options - * issue a OPTIONS http request - * @param uri URI (path on server) or full URL of the document - * @return array list of options supported by the server or NULL in case of error - **/ - function Options( $url ) - { - if( $this->debug & DBGTRACE ) echo "Options( $url )\n"; - $this->responseHeaders = $this->responseBody = ""; - $uri = $this->makeUri( $url ); - - if( $this->sendCommand( "OPTIONS $uri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - if( @$this->responseHeaders["Allow"] == NULL ) - return NULL; - else - return explode( ",", $this->responseHeaders["Allow"] ); - } - - /** - * Post - * issue a POST http request - * @param uri string URI of the document - * @param query_params array parameters to send in the form "parameter name" => value - * @return string response status code (200 if ok) - * @example - * $params = array( "login" => "tiger", "password" => "secret" ); - * $http->post( "/login.php", $params ); - **/ - function Post( $uri, $query_params="" ) - { - if( $this->debug & DBGTRACE ) echo "Post( $uri, $query_params )\n"; - $uri = $this->makeUri( $uri ); - if( is_array($query_params) ) { - $postArray = array(); - foreach( $query_params as $k=>$v ) { - $postArray[] = urlencode($k) . "=" . urlencode($v); - } - $this->requestBody = implode( "&", $postArray); - } - // set the content type for post parameters - $this->addHeader( 'Content-Type', "application/x-www-form-urlencoded" ); -// done in sendCommand() $this->addHeader( 'Content-Length', strlen($this->requestBody) ); - - if( $this->sendCommand( "POST $uri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - $this->removeHeader('Content-Type'); - $this->removeHeader('Content-Length'); - $this->requestBody = ""; - return $this->reply; - } - - /** - * Put - * Send a PUT request - * PUT is the method to sending a file on the server. it is *not* widely supported - * @param uri the location of the file on the server. dont forget the heading "/" - * @param filecontent the content of the file. binary content accepted - * @return string response status code 201 (Created) if ok - * @see RFC2518 "HTTP Extensions for Distributed Authoring WEBDAV" - **/ - function Put( $uri, $filecontent ) - { - if( $this->debug & DBGTRACE ) echo "Put( $uri, [filecontent not displayed )\n"; - $uri = $this->makeUri( $uri ); - $this->requestBody = $filecontent; - if( $this->sendCommand( "PUT $uri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - return $this->reply; - } - - /** - * Send a MOVE HTTP-DAV request - * Move (rename) a file on the server - * @param srcUri the current file location on the server. dont forget the heading "/" - * @param destUri the destination location on the server. this is *not* a full URL - * @param overwrite boolean - true to overwrite an existing destinationn default if yes - * @return string response status code 204 (Unchanged) if ok - * @see RFC2518 "HTTP Extensions for Distributed Authoring WEBDAV" - **/ - function Move( $srcUri, $destUri, $overwrite=true, $scope=0 ) - { - if( $this->debug & DBGTRACE ) echo "Move( $srcUri, $destUri, $overwrite )\n"; - if( $overwrite ) - $this->requestHeaders['Overwrite'] = "T"; - else - $this->requestHeaders['Overwrite'] = "F"; - /* - $destUrl = $this->url['scheme'] . "://" . $this->url['host']; - if( $this->url['port'] != "" ) - $destUrl .= ":" . $this->url['port']; - $destUrl .= $destUri; - $this->requestHeaders['Destination'] = $destUrl; - */ - $this->requestHeaders['Destination'] = $destUri; - $this->requestHeaders['Depth']=$scope; - - if( $this->sendCommand( "MOVE $srcUri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - return $this->reply; - } - - /** - * Send a COPY HTTP-DAV request - * Copy a file -allready on the server- into a new location - * @param srcUri the current file location on the server. dont forget the heading "/" - * @param destUri the destination location on the server. this is *not* a full URL - * @param overwrite boolean - true to overwrite an existing destination - overwrite by default - * @return string response status code 204 (Unchanged) if ok - * @see RFC2518 "HTTP Extensions for Distributed Authoring WEBDAV" - **/ - function Copy( $srcUri, $destUri, $overwrite=true, $scope=0) - { - if( $this->debug & DBGTRACE ) echo "Copy( $srcUri, $destUri, $overwrite )\n"; - if( $overwrite ) - $this->requestHeaders['Overwrite'] = "T"; - else - $this->requestHeaders['Overwrite'] = "F"; - - /* - $destUrl = $this->url['scheme'] . "://" . $this->url['host']; - if( $this->url['port'] != "" ) - $destUrl .= ":" . $this->url['port']; - $destUrl .= $destUri; - $this->requestHeaders['Destination'] = $destUrl; - */ - - $this->requestHeaders['Destination'] = $destUri; - $this->requestHeaders['Depth']=$scope; - - if( $this->sendCommand( "COPY $srcUri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - return $this->reply; - } - - - /** - * Send a MKCOL HTTP-DAV request - * Create a collection (directory) on the server - * @param uri the directory location on the server. dont forget the heading "/" - * @return string response status code 201 (Created) if ok - * @see RFC2518 "HTTP Extensions for Distributed Authoring WEBDAV" - **/ - function MkCol( $uri ) - { - if( $this->debug & DBGTRACE ) echo "Mkcol( $uri )\n"; - // $this->requestHeaders['Overwrite'] = "F"; - $this->requestHeaders['Depth']=0; - if( $this->sendCommand( "MKCOL $uri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - return $this->reply; - } - - /** - * Delete a file on the server using the "DELETE" HTTP-DAV request - * This HTTP method is *not* widely supported - * Only partially supports "collection" deletion, as the XML response is not parsed - * @param uri the location of the file on the server. dont forget the heading "/" - * @return string response status code 204 (Unchanged) if ok - * @see RFC2518 "HTTP Extensions for Distributed Authoring WEBDAV" - **/ - function Delete( $uri, $scope=0) - { - if( $this->debug & DBGTRACE ) echo "Delete( $uri )\n"; - $this->requestHeaders['Depth'] = $scope; - if( $this->sendCommand( "DELETE $uri HTTP/$this->protocolVersion" ) ){ - $this->processReply(); - } - return $this->reply; - } - - /** - - * PropFind - * implements the PROPFIND method - * PROPFIND retrieves meta informations about a resource on the server - * XML reply is not parsed, you'll need to do it - * @param uri the location of the file on the server. dont forget the heading "/" - * @param scope set the scope of the request. - * O : infos about the node only - * 1 : infos for the node and its direct children ( one level) - * Infinity : infos for the node and all its children nodes (recursive) - * @return string response status code - 207 (Multi-Status) if OK - * @see RFC2518 "HTTP Extensions for Distributed Authoring WEBDAV" - **/ - function PropFind( $uri, $scope=0 ) - { - $this->requestBody = ''; - if( $this->debug & DBGTRACE ) echo "Propfind( $uri, $scope )\n"; - $prev_depth=$this->requestHeaders['Depth']; - $this->requestHeaders['Depth'] = $scope; - if( $this->sendCommand( "PROPFIND $uri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - $this->requestHeaders['Depth']=$prev_depth; - return $this->reply; - } - - - /** - * Lock - WARNING: EXPERIMENTAL - * Lock a ressource on the server. XML reply is not parsed, you'll need to do it - * @param $uri URL (relative) of the resource to lock - * @param $lockScope - use "exclusive" for an eclusive lock, "inclusive" for a shared lock - * @param $lockType - acces type of the lock : "write" - * @param $lockScope - use "exclusive" for an eclusive lock, "inclusive" for a shared lock - * @param $lockOwner - an url representing the owner for this lock - * @return server reply code, 200 if ok - **/ - function Lock( $uri, $lockScope, $lockType, $lockOwner ) - { - $body = " - -\n - $lockOwner -\n"; - - $this->requestBody = utf8_encode( $body ); - if( $this->sendCommand( "LOCK $uri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - return $this->reply; - } - - - /** - * Unlock - WARNING: EXPERIMENTAL - * unlock a ressource on the server - * @param $uri URL (relative) of the resource to unlock - * @param $lockToken the lock token given at lock time, eg: opaquelocktoken:e71d4fae-5dec-22d6-fea5-00a0c91e6be4 - * @return server reply code, 204 if ok - **/ - function Unlock( $uri, $lockToken ) - { - $this->addHeader( "Lock-Token", "<$lockToken>" ); - if( $this->sendCommand( "UNLOCK $uri HTTP/$this->protocolVersion" ) ) - $this->processReply(); - return $this->reply; - } - - /** - * getHeaders - * return the response headers - * to be called after a Get() or Head() call - * @return array headers received from server in the form headername => value - * @seeAlso get, head - **/ - function getHeaders() - { - if( $this->debug & DBGTRACE ) echo "getHeaders()\n"; - if( $this->debug & DBGINDATA ) { - echo "DBG.INDATA responseHeaders="; print_r( $this->responseHeaders ); - } - return $this->responseHeaders; - } - - /** - * getHeader - * return the response header "headername" - * @param headername the name of the header - * @return header value or NULL if no such header is defined - **/ - function getHeader( $headername ) - { - if( $this->debug & DBGTRACE ) echo "getHeaderName( $headername )\n"; - return $this->responseHeaders[$headername]; - } - - /** - * getBody - * return the response body - * invoke it after a Get() call for instance, to retrieve the response - * @return string body content - * @seeAlso get, head - **/ - function getBody() - { - if( $this->debug & DBGTRACE ) echo "getBody()\n"; - return $this->responseBody; - } - - /** - * getStatus return the server response's status code - * @return string a status code - * code are divided in classes (where x is a digit) - * - 20x : request processed OK - * - 30x : document moved - * - 40x : client error ( bad url, document not found, etc...) - * - 50x : server error - * @see RFC2616 "Hypertext Transfer Protocol -- HTTP/1.1" - **/ - function getStatus() - { - return $this->reply; - } - - - /** - * getStatusMessage return the full response status, of the form "CODE Message" - * eg. "404 Document not found" - * @return string the message - **/ - function getStatusMessage() - { - return $this->replyString; - } - - - - - /********************************************* - * @scope only protected or private methods below - **/ - - /** - * send a request - * data sent are in order - * a) the command - * b) the request headers if they are defined - * c) the request body if defined - * @return string the server repsonse status code - **/ - function sendCommand( $command ) - { - if( $this->debug & DBGLOW ) echo "sendCommand( $command )\n"; - $this->responseHeaders = array(); - $this->responseBody = ""; - // connect if necessary - if( $this->socket == false or feof( $this->socket) ) { - - if( $this->useProxy ) { - $host = $this->proxyHost; - $port = $this->proxyPort; - } else { - $host = $this->url['host']; - $port = $this->url['port']; - } - if( $port == "" ) $port = 80; - $this->socket = fsockopen( $host, $port, &$this->reply, &$this->replyString ); - if( $this->debug & DBGSOCK ) echo "connexion( $host, $port) - $this->socket\n"; - if( ! $this->socket ) { - if( $this->debug & DBGSOCK ) echo "FAILED : $this->replyString ($this->reply)\n"; - return false; - } - } - - if( $this->requestBody != "" ) { - $this->addHeader( "Content-Length", strlen( $this->requestBody ) ); - } - else { - $this->removeHeader( "Content-Length"); - } - - $this->request = $command; - $cmd = $command . CRLF; - if( is_array( $this->requestHeaders) ) { - foreach( $this->requestHeaders as $k => $v ) { - $cmd .= "$k: $v" . CRLF; - } - } - - if( $this->requestBody != "" ) { - $cmd .= CRLF . $this->requestBody; - } - - // unset body (in case of successive requests) - $this->requestBody = ""; - if( $this->debug & DBGOUTDATA ) echo "DBG.OUTDATA Sending\n$cmd\n"; - - fputs( $this->socket, $cmd . CRLF ); - return true; - } - - function processReply() - { - if( $this->debug & DBGLOW ) echo "processReply()\n"; - - $this->replyString = trim(fgets( $this->socket,1024) ); - if( preg_match( "|^HTTP/\S+ (\d+) |i", $this->replyString, $a )) { - $this->reply = $a[1]; - } else { - $this->reply = EBADRESPONSE; - } - if( $this->debug & DBGINDATA ) echo "replyLine: $this->replyString\n"; - - // get response headers and body - $this->responseHeaders = $this->processHeader(); - $this->responseBody = $this->processBody(); - if ($this->responseHeaders['Connection'] == 'close') { - if( $this->debug & DBGINDATA ) echo "connection closed at server request!"; - fclose($this->socket); - $this->socket=false; - } - -// if( $this->responseHeaders['set-cookie'] ) -// $this->addHeader( "cookie", $this->responseHeaders['set-cookie'] ); - return $this->reply; - } - - /** - * processHeader() reads header lines from socket until the line equals $lastLine - * @scope protected - * @return array of headers with header names as keys and header content as values - **/ - function processHeader( $lastLine = CRLF ) - { - if( $this->debug & DBGLOW ) echo "processHeader( [lastLine] )\n"; - $headers = array(); - $finished = false; - - while ( ( ! $finished ) && ( ! feof($this->socket)) ) { - $str = fgets( $this->socket, 1024 ); - if( $this->debug & DBGINDATA ) echo "HEADER : $str;"; - $finished = ( $str == $lastLine ); - if ( !$finished ) { - list( $hdr, $value ) = split( ": ", $str, 2 ); - // nasty workaround broken multiple same headers (eg. Set-Cookie headers) @FIXME - if( isset( $headers[$hdr]) ) - $headers[$hdr] .= "; " . trim($value); - else - $headers[$hdr] = trim($value); - } - } - return $headers; - } - - /** - * processBody() reads the body from the socket - * the body is the "real" content of the reply - * @return string body content - * @scope private - **/ - function processBody() - { - $failureCount = 0; - - $data=''; - if( $this->debug & DBGLOW ) echo "processBody()\n"; - - if ( $this->responseHeaders['Transfer-Encoding']=='chunked' ) - { - // chunked encoding - if( $this->debug & DBGSOCK ) echo "DBG.SOCK chunked encoding..\n"; - $length = fgets($this->socket, 1024); - $length = hexdec($length); - - while (true) { - if ($length == 0) { break; } - $data .= fread($this->socket, $length); - if( $this->debug & DBGSOCK ) echo "DBG.SOCK chunked encoding: read $length bytes\n"; - fgets($this->socket, 1024); - $length = fgets($this->socket, 1024); - $length = hexdec($length); - } - fgets($this->socket, 1024); - - } - else if ($this->responseHeaders['Content-Length'] ) - { - $length = $this->responseHeaders['Content-Length']; - while (!feof($this->socket)) { - $data .= fread($this->socket, 1024); - } - if( $this->debug & DBGSOCK ) echo "DBG.SOCK socket_read using Content-Length ($length)\n"; - - } - else { - if( $this->debug & DBGSOCK ) echo "Not chunked, dont know how big?..\n"; - $data = ""; - $counter = 0; - socket_set_blocking( $this->socket, true ); - socket_set_timeout($this->socket,2); - $ts1=time(); - do{ - $status = socket_get_status( $this->socket ); -/* if( $this->debug & DBGSOCK ) - echo " Socket status: "; print_r($status); -*/ if( feof($this->socket)) { - if( $this->debug & DBGSOCK ) echo "DBG.SOCK eof met, finished socket_read\n"; - break; - } - if( $status['unread_bytes'] > 0 ) { - $buffer = fread( $this->socket, $status['unread_bytes'] ); - $counter = 0; - } else { - $ts=time(); - $buffer = fread( $this->socket, 1024 ); - - sleep(0.1); - $failureCount++; - //print "elapsed ".(time()-$ts)."
"; - } - $data .= $buffer; - - - } while( $status['unread_bytes'] > 0 || $counter++ < 10 ); - //print "total ".(time()-$ts1)."
"; - - if( $this->debug & DBGSOCK ) { - echo "DBG.SOCK Counter:$counter\nRead failure #: $failureCount\n"; - echo " Socket status: "; print_r($status); - } - socket_set_blocking( $this->socket, true ); - } - $len = strlen($data); - if( $this->debug & DBGSOCK ) echo "DBG.SOCK read $len bytes"; - - return $data; - } - - - /** - * Calculate and return the URI to be sent ( proxy purpose ) - * @param the local URI - * @return URI to be used in the HTTP request - * @scope private - **/ - - function makeUri( $uri ) - { - $a = parse_url( $uri ); - - if( isset($a['scheme']) && isset($a['host']) ) { - $this->url = $a; - } else { - unset( $this->url['query']); - unset( $this->url['fragment']); - $this->url = array_merge( $this->url, $a ); - } - if( $this->useProxy ) { - $requesturi= "http://" . $this->url['host'] . ( empty($this->url['port']) ? "" : ":" . $this->url['port'] ) . $this->url['path'] . ( empty($this->url['query']) ? "" : "?" . $this->url['query'] ); - } else { - $requesturi = $this->url['path'] . (empty( $this->url['query'] ) ? "" : "?" . $this->url['query']); - } - return $requesturi; - } - -} // end class net_http_client - - -?>