Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117754571
Request2.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
35 KB
Referenced Files
None
Subscribers
None
Request2.php
View Options
<?php
/**
* Class representing a HTTP request message
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version SVN: $Id: Request2.php 315409 2011-08-24 07:29:23Z avb $
* @link http://pear.php.net/package/HTTP_Request2
*/
/**
* A class representing an URL as per RFC 3986.
*/
require_once
'Net/URL2.php'
;
/**
* Exception class for HTTP_Request2 package
*/
require_once
'HTTP/Request2/Exception.php'
;
/**
* Class representing a HTTP request message
*
* @category HTTP
* @package HTTP_Request2
* @author Alexey Borzov <avb@php.net>
* @version Release: 2.0.0
* @link http://tools.ietf.org/html/rfc2616#section-5
*/
class
HTTP_Request2
implements
SplSubject
{
/**#@+
* Constants for HTTP request methods
*
* @link http://tools.ietf.org/html/rfc2616#section-5.1.1
*/
const
METHOD_OPTIONS
=
'OPTIONS'
;
const
METHOD_GET
=
'GET'
;
const
METHOD_HEAD
=
'HEAD'
;
const
METHOD_POST
=
'POST'
;
const
METHOD_PUT
=
'PUT'
;
const
METHOD_DELETE
=
'DELETE'
;
const
METHOD_TRACE
=
'TRACE'
;
const
METHOD_CONNECT
=
'CONNECT'
;
/**#@-*/
/**#@+
* Constants for HTTP authentication schemes
*
* @link http://tools.ietf.org/html/rfc2617
*/
const
AUTH_BASIC
=
'basic'
;
const
AUTH_DIGEST
=
'digest'
;
/**#@-*/
/**
* Regular expression used to check for invalid symbols in RFC 2616 tokens
* @link http://pear.php.net/bugs/bug.php?id=15630
*/
const
REGEXP_INVALID_TOKEN
=
'![
\x
00-
\x
1f
\x
7f-
\x
ff()<>@,;:
\\\\
"/
\[\]
?={}
\s
]!'
;
/**
* Regular expression used to check for invalid symbols in cookie strings
* @link http://pear.php.net/bugs/bug.php?id=15630
* @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html
*/
const
REGEXP_INVALID_COOKIE
=
'/[
\s
,;]/'
;
/**
* Fileinfo magic database resource
* @var resource
* @see detectMimeType()
*/
private
static
$_fileinfoDb
;
/**
* Observers attached to the request (instances of SplObserver)
* @var array
*/
protected
$observers
=
array
();
/**
* Request URL
* @var Net_URL2
*/
protected
$url
;
/**
* Request method
* @var string
*/
protected
$method
=
self
::
METHOD_GET
;
/**
* Authentication data
* @var array
* @see getAuth()
*/
protected
$auth
;
/**
* Request headers
* @var array
*/
protected
$headers
=
array
();
/**
* Configuration parameters
* @var array
* @see setConfig()
*/
protected
$config
=
array
(
'adapter'
=>
'HTTP_Request2_Adapter_Socket'
,
'connect_timeout'
=>
10
,
'timeout'
=>
0
,
'use_brackets'
=>
true
,
'protocol_version'
=>
'1.1'
,
'buffer_size'
=>
16384
,
'store_body'
=>
true
,
'proxy_host'
=>
''
,
'proxy_port'
=>
''
,
'proxy_user'
=>
''
,
'proxy_password'
=>
''
,
'proxy_auth_scheme'
=>
self
::
AUTH_BASIC
,
'ssl_verify_peer'
=>
true
,
'ssl_verify_host'
=>
true
,
'ssl_cafile'
=>
null
,
'ssl_capath'
=>
null
,
'ssl_local_cert'
=>
null
,
'ssl_passphrase'
=>
null
,
'digest_compat_ie'
=>
false
,
'follow_redirects'
=>
false
,
'max_redirects'
=>
5
,
'strict_redirects'
=>
false
);
/**
* Last event in request / response handling, intended for observers
* @var array
* @see getLastEvent()
*/
protected
$lastEvent
=
array
(
'name'
=>
'start'
,
'data'
=>
null
);
/**
* Request body
* @var string|resource
* @see setBody()
*/
protected
$body
=
''
;
/**
* Array of POST parameters
* @var array
*/
protected
$postParams
=
array
();
/**
* Array of file uploads (for multipart/form-data POST requests)
* @var array
*/
protected
$uploads
=
array
();
/**
* Adapter used to perform actual HTTP request
* @var HTTP_Request2_Adapter
*/
protected
$adapter
;
/**
* Cookie jar to persist cookies between requests
* @var HTTP_Request2_CookieJar
*/
protected
$cookieJar
=
null
;
/**
* Constructor. Can set request URL, method and configuration array.
*
* Also sets a default value for User-Agent header.
*
* @param string|Net_Url2 Request URL
* @param string Request method
* @param array Configuration for this Request instance
*/
public
function
__construct
(
$url
=
null
,
$method
=
self
::
METHOD_GET
,
array
$config
=
array
())
{
$this
->
setConfig
(
$config
);
if
(!
empty
(
$url
))
{
$this
->
setUrl
(
$url
);
}
if
(!
empty
(
$method
))
{
$this
->
setMethod
(
$method
);
}
$this
->
setHeader
(
'user-agent'
,
'HTTP_Request2/2.0.0 '
.
'(http://pear.php.net/package/http_request2) '
.
'PHP/'
.
phpversion
());
}
/**
* Sets the URL for this request
*
* If the URL has userinfo part (username & password) these will be removed
* and converted to auth data. If the URL does not have a path component,
* that will be set to '/'.
*
* @param string|Net_URL2 Request URL
* @return HTTP_Request2
* @throws HTTP_Request2_LogicException
*/
public
function
setUrl
(
$url
)
{
if
(
is_string
(
$url
))
{
$url
=
new
Net_URL2
(
$url
,
array
(
Net_URL2
::
OPTION_USE_BRACKETS
=>
$this
->
config
[
'use_brackets'
])
);
}
if
(!
$url
instanceof
Net_URL2
)
{
throw
new
HTTP_Request2_LogicException
(
'Parameter is not a valid HTTP URL'
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
// URL contains username / password?
if
(
$url
->
getUserinfo
())
{
$username
=
$url
->
getUser
();
$password
=
$url
->
getPassword
();
$this
->
setAuth
(
rawurldecode
(
$username
),
$password
?
rawurldecode
(
$password
):
''
);
$url
->
setUserinfo
(
''
);
}
if
(
''
==
$url
->
getPath
())
{
$url
->
setPath
(
'/'
);
}
$this
->
url
=
$url
;
return
$this
;
}
/**
* Returns the request URL
*
* @return Net_URL2
*/
public
function
getUrl
()
{
return
$this
->
url
;
}
/**
* Sets the request method
*
* @param string
* @return HTTP_Request2
* @throws HTTP_Request2_LogicException if the method name is invalid
*/
public
function
setMethod
(
$method
)
{
// Method name should be a token: http://tools.ietf.org/html/rfc2616#section-5.1.1
if
(
preg_match
(
self
::
REGEXP_INVALID_TOKEN
,
$method
))
{
throw
new
HTTP_Request2_LogicException
(
"Invalid request method '{$method}'"
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
$this
->
method
=
$method
;
return
$this
;
}
/**
* Returns the request method
*
* @return string
*/
public
function
getMethod
()
{
return
$this
->
method
;
}
/**
* Sets the configuration parameter(s)
*
* The following parameters are available:
* <ul>
* <li> 'adapter' - adapter to use (string)</li>
* <li> 'connect_timeout' - Connection timeout in seconds (integer)</li>
* <li> 'timeout' - Total number of seconds a request can take.
* Use 0 for no limit, should be greater than
* 'connect_timeout' if set (integer)</li>
* <li> 'use_brackets' - Whether to append [] to array variable names (bool)</li>
* <li> 'protocol_version' - HTTP Version to use, '1.0' or '1.1' (string)</li>
* <li> 'buffer_size' - Buffer size to use for reading and writing (int)</li>
* <li> 'store_body' - Whether to store response body in response object.
* Set to false if receiving a huge response and
* using an Observer to save it (boolean)</li>
* <li> 'proxy_host' - Proxy server host (string)</li>
* <li> 'proxy_port' - Proxy server port (integer)</li>
* <li> 'proxy_user' - Proxy auth username (string)</li>
* <li> 'proxy_password' - Proxy auth password (string)</li>
* <li> 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)</li>
* <li> 'ssl_verify_peer' - Whether to verify peer's SSL certificate (bool)</li>
* <li> 'ssl_verify_host' - Whether to check that Common Name in SSL
* certificate matches host name (bool)</li>
* <li> 'ssl_cafile' - Cerificate Authority file to verify the peer
* with (use with 'ssl_verify_peer') (string)</li>
* <li> 'ssl_capath' - Directory holding multiple Certificate
* Authority files (string)</li>
* <li> 'ssl_local_cert' - Name of a file containing local cerificate (string)</li>
* <li> 'ssl_passphrase' - Passphrase with which local certificate
* was encoded (string)</li>
* <li> 'digest_compat_ie' - Whether to imitate behaviour of MSIE 5 and 6
* in using URL without query string in digest
* authentication (boolean)</li>
* <li> 'follow_redirects' - Whether to automatically follow HTTP Redirects (boolean)</li>
* <li> 'max_redirects' - Maximum number of redirects to follow (integer)</li>
* <li> 'strict_redirects' - Whether to keep request method on redirects via status 301 and
* 302 (true, needed for compatibility with RFC 2616)
* or switch to GET (false, needed for compatibility with most
* browsers) (boolean)</li>
* </ul>
*
* @param string|array configuration parameter name or array
* ('parameter name' => 'parameter value')
* @param mixed parameter value if $nameOrConfig is not an array
* @return HTTP_Request2
* @throws HTTP_Request2_LogicException If the parameter is unknown
*/
public
function
setConfig
(
$nameOrConfig
,
$value
=
null
)
{
if
(
is_array
(
$nameOrConfig
))
{
foreach
(
$nameOrConfig
as
$name
=>
$value
)
{
$this
->
setConfig
(
$name
,
$value
);
}
}
else
{
if
(!
array_key_exists
(
$nameOrConfig
,
$this
->
config
))
{
throw
new
HTTP_Request2_LogicException
(
"Unknown configuration parameter '{$nameOrConfig}'"
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
$this
->
config
[
$nameOrConfig
]
=
$value
;
}
return
$this
;
}
/**
* Returns the value(s) of the configuration parameter(s)
*
* @param string parameter name
* @return mixed value of $name parameter, array of all configuration
* parameters if $name is not given
* @throws HTTP_Request2_LogicException If the parameter is unknown
*/
public
function
getConfig
(
$name
=
null
)
{
if
(
null
===
$name
)
{
return
$this
->
config
;
}
elseif
(!
array_key_exists
(
$name
,
$this
->
config
))
{
throw
new
HTTP_Request2_LogicException
(
"Unknown configuration parameter '{$name}'"
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
return
$this
->
config
[
$name
];
}
/**
* Sets the autentification data
*
* @param string user name
* @param string password
* @param string authentication scheme
* @return HTTP_Request2
*/
public
function
setAuth
(
$user
,
$password
=
''
,
$scheme
=
self
::
AUTH_BASIC
)
{
if
(
empty
(
$user
))
{
$this
->
auth
=
null
;
}
else
{
$this
->
auth
=
array
(
'user'
=>
(
string
)
$user
,
'password'
=>
(
string
)
$password
,
'scheme'
=>
$scheme
);
}
return
$this
;
}
/**
* Returns the authentication data
*
* The array has the keys 'user', 'password' and 'scheme', where 'scheme'
* is one of the HTTP_Request2::AUTH_* constants.
*
* @return array
*/
public
function
getAuth
()
{
return
$this
->
auth
;
}
/**
* Sets request header(s)
*
* The first parameter may be either a full header string 'header: value' or
* header name. In the former case $value parameter is ignored, in the latter
* the header's value will either be set to $value or the header will be
* removed if $value is null. The first parameter can also be an array of
* headers, in that case method will be called recursively.
*
* Note that headers are treated case insensitively as per RFC 2616.
*
* <code>
* $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar'
* $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz'
* $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux'
* $req->setHeader('FOO'); // removes 'Foo' header from request
* </code>
*
* @param string|array header name, header string ('Header: value')
* or an array of headers
* @param string|array|null header value if $name is not an array,
* header will be removed if value is null
* @param bool whether to replace previous header with the
* same name or append to its value
* @return HTTP_Request2
* @throws HTTP_Request2_LogicException
*/
public
function
setHeader
(
$name
,
$value
=
null
,
$replace
=
true
)
{
if
(
is_array
(
$name
))
{
foreach
(
$name
as
$k
=>
$v
)
{
if
(
is_string
(
$k
))
{
$this
->
setHeader
(
$k
,
$v
,
$replace
);
}
else
{
$this
->
setHeader
(
$v
,
null
,
$replace
);
}
}
}
else
{
if
(
null
===
$value
&&
strpos
(
$name
,
':'
))
{
list
(
$name
,
$value
)
=
array_map
(
'trim'
,
explode
(
':'
,
$name
,
2
));
}
// Header name should be a token: http://tools.ietf.org/html/rfc2616#section-4.2
if
(
preg_match
(
self
::
REGEXP_INVALID_TOKEN
,
$name
))
{
throw
new
HTTP_Request2_LogicException
(
"Invalid header name '{$name}'"
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
// Header names are case insensitive anyway
$name
=
strtolower
(
$name
);
if
(
null
===
$value
)
{
unset
(
$this
->
headers
[
$name
]);
}
else
{
if
(
is_array
(
$value
))
{
$value
=
implode
(
', '
,
array_map
(
'trim'
,
$value
));
}
elseif
(
is_string
(
$value
))
{
$value
=
trim
(
$value
);
}
if
(!
isset
(
$this
->
headers
[
$name
])
||
$replace
)
{
$this
->
headers
[
$name
]
=
$value
;
}
else
{
$this
->
headers
[
$name
]
.=
', '
.
$value
;
}
}
}
return
$this
;
}
/**
* Returns the request headers
*
* The array is of the form ('header name' => 'header value'), header names
* are lowercased
*
* @return array
*/
public
function
getHeaders
()
{
return
$this
->
headers
;
}
/**
* Adds a cookie to the request
*
* If the request does not have a CookieJar object set, this method simply
* appends a cookie to "Cookie:" header.
*
* If a CookieJar object is available, the cookie is stored in that object.
* Data from request URL will be used for setting its 'domain' and 'path'
* parameters, 'expires' and 'secure' will be set to null and false,
* respectively. If you need further control, use CookieJar's methods.
*
* @param string cookie name
* @param string cookie value
* @return HTTP_Request2
* @throws HTTP_Request2_LogicException
* @see setCookieJar()
*/
public
function
addCookie
(
$name
,
$value
)
{
if
(!
empty
(
$this
->
cookieJar
))
{
$this
->
cookieJar
->
store
(
array
(
'name'
=>
$name
,
'value'
=>
$value
),
$this
->
url
);
}
else
{
$cookie
=
$name
.
'='
.
$value
;
if
(
preg_match
(
self
::
REGEXP_INVALID_COOKIE
,
$cookie
))
{
throw
new
HTTP_Request2_LogicException
(
"Invalid cookie: '{$cookie}'"
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
$cookies
=
empty
(
$this
->
headers
[
'cookie'
])?
''
:
$this
->
headers
[
'cookie'
]
.
'; '
;
$this
->
setHeader
(
'cookie'
,
$cookies
.
$cookie
);
}
return
$this
;
}
/**
* Sets the request body
*
* If you provide file pointer rather than file name, it should support
* fstat() and rewind() operations.
*
* @param string|resource|HTTP_Request2_MultipartBody Either a string
* with the body or filename containing body or pointer to
* an open file or object with multipart body data
* @param bool Whether first parameter is a filename
* @return HTTP_Request2
* @throws HTTP_Request2_LogicException
*/
public
function
setBody
(
$body
,
$isFilename
=
false
)
{
if
(!
$isFilename
&&
!
is_resource
(
$body
))
{
if
(!
$body
instanceof
HTTP_Request2_MultipartBody
)
{
$this
->
body
=
(
string
)
$body
;
}
else
{
$this
->
body
=
$body
;
}
}
else
{
$fileData
=
$this
->
fopenWrapper
(
$body
,
empty
(
$this
->
headers
[
'content-type'
]));
$this
->
body
=
$fileData
[
'fp'
];
if
(
empty
(
$this
->
headers
[
'content-type'
]))
{
$this
->
setHeader
(
'content-type'
,
$fileData
[
'type'
]);
}
}
$this
->
postParams
=
$this
->
uploads
=
array
();
return
$this
;
}
/**
* Returns the request body
*
* @return string|resource|HTTP_Request2_MultipartBody
*/
public
function
getBody
()
{
if
(
self
::
METHOD_POST
==
$this
->
method
&&
(!
empty
(
$this
->
postParams
)
||
!
empty
(
$this
->
uploads
))
)
{
if
(
0
===
strpos
(
$this
->
headers
[
'content-type'
],
'application/x-www-form-urlencoded'
))
{
$body
=
http_build_query
(
$this
->
postParams
,
''
,
'&'
);
if
(!
$this
->
getConfig
(
'use_brackets'
))
{
$body
=
preg_replace
(
'/%5B
\d
+%5D=/'
,
'='
,
$body
);
}
// support RFC 3986 by not encoding '~' symbol (request #15368)
return
str_replace
(
'%7E'
,
'~'
,
$body
);
}
elseif
(
0
===
strpos
(
$this
->
headers
[
'content-type'
],
'multipart/form-data'
))
{
require_once
'HTTP/Request2/MultipartBody.php'
;
return
new
HTTP_Request2_MultipartBody
(
$this
->
postParams
,
$this
->
uploads
,
$this
->
getConfig
(
'use_brackets'
)
);
}
}
return
$this
->
body
;
}
/**
* Adds a file to form-based file upload
*
* Used to emulate file upload via a HTML form. The method also sets
* Content-Type of HTTP request to 'multipart/form-data'.
*
* If you just want to send the contents of a file as the body of HTTP
* request you should use setBody() method.
*
* If you provide file pointers rather than file names, they should support
* fstat() and rewind() operations.
*
* @param string name of file-upload field
* @param string|resource|array full name of local file, pointer to
* open file or an array of files
* @param string filename to send in the request
* @param string content-type of file being uploaded
* @return HTTP_Request2
* @throws HTTP_Request2_LogicException
*/
public
function
addUpload
(
$fieldName
,
$filename
,
$sendFilename
=
null
,
$contentType
=
null
)
{
if
(!
is_array
(
$filename
))
{
$fileData
=
$this
->
fopenWrapper
(
$filename
,
empty
(
$contentType
));
$this
->
uploads
[
$fieldName
]
=
array
(
'fp'
=>
$fileData
[
'fp'
],
'filename'
=>
!
empty
(
$sendFilename
)?
$sendFilename
:(
is_string
(
$filename
)?
basename
(
$filename
):
'anonymous.blob'
)
,
'size'
=>
$fileData
[
'size'
],
'type'
=>
empty
(
$contentType
)?
$fileData
[
'type'
]:
$contentType
);
}
else
{
$fps
=
$names
=
$sizes
=
$types
=
array
();
foreach
(
$filename
as
$f
)
{
if
(!
is_array
(
$f
))
{
$f
=
array
(
$f
);
}
$fileData
=
$this
->
fopenWrapper
(
$f
[
0
],
empty
(
$f
[
2
]));
$fps
[]
=
$fileData
[
'fp'
];
$names
[]
=
!
empty
(
$f
[
1
])?
$f
[
1
]
:(
is_string
(
$f
[
0
])?
basename
(
$f
[
0
]):
'anonymous.blob'
);
$sizes
[]
=
$fileData
[
'size'
];
$types
[]
=
empty
(
$f
[
2
])?
$fileData
[
'type'
]:
$f
[
2
];
}
$this
->
uploads
[
$fieldName
]
=
array
(
'fp'
=>
$fps
,
'filename'
=>
$names
,
'size'
=>
$sizes
,
'type'
=>
$types
);
}
if
(
empty
(
$this
->
headers
[
'content-type'
])
||
'application/x-www-form-urlencoded'
==
$this
->
headers
[
'content-type'
]
)
{
$this
->
setHeader
(
'content-type'
,
'multipart/form-data'
);
}
return
$this
;
}
/**
* Adds POST parameter(s) to the request.
*
* @param string|array parameter name or array ('name' => 'value')
* @param mixed parameter value (can be an array)
* @return HTTP_Request2
*/
public
function
addPostParameter
(
$name
,
$value
=
null
)
{
if
(!
is_array
(
$name
))
{
$this
->
postParams
[
$name
]
=
$value
;
}
else
{
foreach
(
$name
as
$k
=>
$v
)
{
$this
->
addPostParameter
(
$k
,
$v
);
}
}
if
(
empty
(
$this
->
headers
[
'content-type'
]))
{
$this
->
setHeader
(
'content-type'
,
'application/x-www-form-urlencoded'
);
}
return
$this
;
}
/**
* Attaches a new observer
*
* @param SplObserver
*/
public
function
attach
(
SplObserver
$observer
)
{
foreach
(
$this
->
observers
as
$attached
)
{
if
(
$attached
===
$observer
)
{
return
;
}
}
$this
->
observers
[]
=
$observer
;
}
/**
* Detaches an existing observer
*
* @param SplObserver
*/
public
function
detach
(
SplObserver
$observer
)
{
foreach
(
$this
->
observers
as
$key
=>
$attached
)
{
if
(
$attached
===
$observer
)
{
unset
(
$this
->
observers
[
$key
]);
return
;
}
}
}
/**
* Notifies all observers
*/
public
function
notify
()
{
foreach
(
$this
->
observers
as
$observer
)
{
$observer
->
update
(
$this
);
}
}
/**
* Sets the last event
*
* Adapters should use this method to set the current state of the request
* and notify the observers.
*
* @param string event name
* @param mixed event data
*/
public
function
setLastEvent
(
$name
,
$data
=
null
)
{
$this
->
lastEvent
=
array
(
'name'
=>
$name
,
'data'
=>
$data
);
$this
->
notify
();
}
/**
* Returns the last event
*
* Observers should use this method to access the last change in request.
* The following event names are possible:
* <ul>
* <li>'connect' - after connection to remote server,
* data is the destination (string)</li>
* <li>'disconnect' - after disconnection from server</li>
* <li>'sentHeaders' - after sending the request headers,
* data is the headers sent (string)</li>
* <li>'sentBodyPart' - after sending a part of the request body,
* data is the length of that part (int)</li>
* <li>'sentBody' - after sending the whole request body,
* data is request body length (int)</li>
* <li>'receivedHeaders' - after receiving the response headers,
* data is HTTP_Request2_Response object</li>
* <li>'receivedBodyPart' - after receiving a part of the response
* body, data is that part (string)</li>
* <li>'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still
* encoded by Content-Encoding</li>
* <li>'receivedBody' - after receiving the complete response
* body, data is HTTP_Request2_Response object</li>
* </ul>
* Different adapters may not send all the event types. Mock adapter does
* not send any events to the observers.
*
* @return array The array has two keys: 'name' and 'data'
*/
public
function
getLastEvent
()
{
return
$this
->
lastEvent
;
}
/**
* Sets the adapter used to actually perform the request
*
* You can pass either an instance of a class implementing HTTP_Request2_Adapter
* or a class name. The method will only try to include a file if the class
* name starts with HTTP_Request2_Adapter_, it will also try to prepend this
* prefix to the class name if it doesn't contain any underscores, so that
* <code>
* $request->setAdapter('curl');
* </code>
* will work.
*
* @param string|HTTP_Request2_Adapter
* @return HTTP_Request2
* @throws HTTP_Request2_LogicException
*/
public
function
setAdapter
(
$adapter
)
{
if
(
is_string
(
$adapter
))
{
if
(!
class_exists
(
$adapter
,
false
))
{
if
(
false
===
strpos
(
$adapter
,
'_'
))
{
$adapter
=
'HTTP_Request2_Adapter_'
.
ucfirst
(
$adapter
);
}
if
(
preg_match
(
'/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/'
,
$adapter
))
{
include_once
str_replace
(
'_'
,
DIRECTORY_SEPARATOR
,
$adapter
)
.
'.php'
;
}
if
(!
class_exists
(
$adapter
,
false
))
{
throw
new
HTTP_Request2_LogicException
(
"Class {$adapter} not found"
,
HTTP_Request2_Exception
::
MISSING_VALUE
);
}
}
$adapter
=
new
$adapter
;
}
if
(!
$adapter
instanceof
HTTP_Request2_Adapter
)
{
throw
new
HTTP_Request2_LogicException
(
'Parameter is not a HTTP request adapter'
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
$this
->
adapter
=
$adapter
;
return
$this
;
}
/**
* Sets the cookie jar
*
* A cookie jar is used to maintain cookies across HTTP requests and
* responses. Cookies from jar will be automatically added to the request
* headers based on request URL.
*
* @param HTTP_Request2_CookieJar|bool Existing CookieJar object, true to
* create a new one, false to remove
*/
public
function
setCookieJar
(
$jar
=
true
)
{
if
(!
class_exists
(
'HTTP_Request2_CookieJar'
,
false
))
{
require_once
'HTTP/Request2/CookieJar.php'
;
}
if
(
$jar
instanceof
HTTP_Request2_CookieJar
)
{
$this
->
cookieJar
=
$jar
;
}
elseif
(
true
===
$jar
)
{
$this
->
cookieJar
=
new
HTTP_Request2_CookieJar
();
}
elseif
(!
$jar
)
{
$this
->
cookieJar
=
null
;
}
else
{
throw
new
HTTP_Request2_LogicException
(
'Invalid parameter passed to setCookieJar()'
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
return
$this
;
}
/**
* Returns current CookieJar object or null if none
*
* @return HTTP_Request2_CookieJar|null
*/
public
function
getCookieJar
()
{
return
$this
->
cookieJar
;
}
/**
* Sends the request and returns the response
*
* @throws HTTP_Request2_Exception
* @return HTTP_Request2_Response
*/
public
function
send
()
{
// Sanity check for URL
if
(!
$this
->
url
instanceof
Net_URL2
||
!
$this
->
url
->
isAbsolute
()
||
!
in_array
(
strtolower
(
$this
->
url
->
getScheme
()),
array
(
'https'
,
'http'
))
)
{
throw
new
HTTP_Request2_LogicException
(
'HTTP_Request2 needs an absolute HTTP(S) request URL, '
.
(
$this
->
url
instanceof
Net_URL2
?
"'"
.
$this
->
url
->
__toString
()
.
"'"
:
'none'
)
.
' given'
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
if
(
empty
(
$this
->
adapter
))
{
$this
->
setAdapter
(
$this
->
getConfig
(
'adapter'
));
}
// magic_quotes_runtime may break file uploads and chunked response
// processing; see bug #4543. Don't use ini_get() here; see bug #16440.
if
(
$magicQuotes
=
get_magic_quotes_runtime
())
{
set_magic_quotes_runtime
(
false
);
}
// force using single byte encoding if mbstring extension overloads
// strlen() and substr(); see bug #1781, bug #10605
if
(
extension_loaded
(
'mbstring'
)
&&
(
2
&
ini_get
(
'mbstring.func_overload'
)))
{
$oldEncoding
=
mb_internal_encoding
();
mb_internal_encoding
(
'iso-8859-1'
);
}
try
{
$response
=
$this
->
adapter
->
sendRequest
(
$this
);
}
catch
(
Exception
$e
)
{
}
// cleanup in either case (poor man's "finally" clause)
if
(
$magicQuotes
)
{
set_magic_quotes_runtime
(
true
);
}
if
(!
empty
(
$oldEncoding
))
{
mb_internal_encoding
(
$oldEncoding
);
}
// rethrow the exception
if
(!
empty
(
$e
))
{
throw
$e
;
}
return
$response
;
}
/**
* Wrapper around fopen()/fstat() used by setBody() and addUpload()
*
* @param string|resource file name or pointer to open file
* @param bool whether to try autodetecting MIME type of file,
* will only work if $file is a filename, not pointer
* @return array array('fp' => file pointer, 'size' => file size, 'type' => MIME type)
* @throws HTTP_Request2_LogicException
*/
protected
function
fopenWrapper
(
$file
,
$detectType
=
false
)
{
if
(!
is_string
(
$file
)
&&
!
is_resource
(
$file
))
{
throw
new
HTTP_Request2_LogicException
(
"Filename or file pointer resource expected"
,
HTTP_Request2_Exception
::
INVALID_ARGUMENT
);
}
$fileData
=
array
(
'fp'
=>
is_string
(
$file
)?
null
:
$file
,
'type'
=>
'application/octet-stream'
,
'size'
=>
0
);
if
(
is_string
(
$file
))
{
$track
=
@
ini_set
(
'track_errors'
,
1
);
if
(!(
$fileData
[
'fp'
]
=
@
fopen
(
$file
,
'rb'
)))
{
$e
=
new
HTTP_Request2_LogicException
(
$php_errormsg
,
HTTP_Request2_Exception
::
READ_ERROR
);
}
@
ini_set
(
'track_errors'
,
$track
);
if
(
isset
(
$e
))
{
throw
$e
;
}
if
(
$detectType
)
{
$fileData
[
'type'
]
=
self
::
detectMimeType
(
$file
);
}
}
if
(!(
$stat
=
fstat
(
$fileData
[
'fp'
])))
{
throw
new
HTTP_Request2_LogicException
(
"fstat() call failed"
,
HTTP_Request2_Exception
::
READ_ERROR
);
}
$fileData
[
'size'
]
=
$stat
[
'size'
];
return
$fileData
;
}
/**
* Tries to detect MIME type of a file
*
* The method will try to use fileinfo extension if it is available,
* deprecated mime_content_type() function in the other case. If neither
* works, default 'application/octet-stream' MIME type is returned
*
* @param string filename
* @return string file MIME type
*/
protected
static
function
detectMimeType
(
$filename
)
{
// finfo extension from PECL available
if
(
function_exists
(
'finfo_open'
))
{
if
(!
isset
(
self
::
$_fileinfoDb
))
{
self
::
$_fileinfoDb
=
@
finfo_open
(
FILEINFO_MIME
);
}
if
(
self
::
$_fileinfoDb
)
{
$info
=
finfo_file
(
self
::
$_fileinfoDb
,
$filename
);
}
}
// (deprecated) mime_content_type function available
if
(
empty
(
$info
)
&&
function_exists
(
'mime_content_type'
))
{
return
mime_content_type
(
$filename
);
}
return
empty
(
$info
)?
'application/octet-stream'
:
$info
;
}
}
?>
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, Apr 4, 7:07 AM (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18777438
Default Alt Text
Request2.php (35 KB)
Attached To
Mode
rWAP webadmin
Attached
Detach File
Event Timeline