Repository URL to install this package:
|
Version:
2.4.7 ▾
|
<?php
namespace CrazyFactory\PrintIpp;
class HttpClass
{
// variables declaration
public $debug;
public $html_debug;
public $timeout = 30; // time waiting for connection, seconds
public $data_timeout = 30; // time waiting for data, milliseconds
public $data_chunk_timeout = 1; // time waiting between data chunks, millisecond
public $force_multipart_form_post;
public $username;
public $password;
public $request_headers = array();
public $request_body = "Not a useful information";
public $status;
public $window_size = 1024; // chunk size of data
public $with_exceptions = 0; // compatibility mode for old scripts
public $port;
public $host;
private $default_port = 631;
private $headers;
private $reply_headers = array();
private $reply_body = array();
private $connection;
private $arguments;
private $bodystream = array();
private $last_limit;
private $connected;
private $nc = 1;
private $user_agent = "PRINTIPP/0.81+CVS";
private $readed_bytes = 0;
public function __construct()
{
true;
}
/*********************
*
* Public functions
*
**********************/
public function GetRequestArguments($url, &$arguments)
{
$this->arguments = array();
$this->arguments["URL"] = $arguments["URL"] = $url;
$this->arguments["RequestMethod"] = $arguments["RequestMethod"] = "POST";
$this->headers["Content-Length"] = 0;
$this->headers["Content-Type"] = "application/octet-stream";
$this->headers["Host"] = $this->host;
$this->headers["User-Agent"] = $this->user_agent;
//$this->headers["Expect"] = "100-continue";
}
public function Open($arguments)
{
$this->connected = false;
$url = $arguments["URL"];
$port = $this->default_port;
#$url = split (':', $url, 2);
$url = preg_split('#:#', $url, 2);
$transport_type = $url[0];
$unix = false;
switch ($transport_type) {
case 'http':
$transport_type = 'tcp://';
break;
case 'https':
$transport_type = 'tls://';
break;
case 'unix':
$transport_type = 'unix://';
$port = 0;
$unix = true;
break;
default:
$transport_type = 'tcp://';
break;
}
$url = $url[1];
if (!$unix) {
#$url = split ("/", preg_replace ("#^/{1,}#", '', $url), 2);
$url = preg_split("#/#", preg_replace("#^/{1,}#", '', $url), 2);
$url = $url[0];
$port = $this->port;
$error = sprintf("Cannot resolve url: %s", $url);
$ip = gethostbyname($url);
$ip = @gethostbyaddr($ip);
if (!$ip) {
return $this->_HttpError($error, E_USER_WARNING);
}
if (strstr($url, ":")) // we got an ipv6 address
{
if (!strstr($url, "[")) // it is not escaped
{
$url = sprintf("[%s]", $url);
}
}
}
$this->connection = @fsockopen($transport_type . $url, $port, $errno, $errstr, $this->timeout);
$error =
sprintf('Unable to connect to "%s%s port %s": %s', $transport_type,
$url, $port, $errstr);
if (!$this->connection) {
return $this->_HttpError($error, E_USER_WARNING);
}
$this->connected = true;
return array(true, "success");
}
public function SendRequest($arguments)
{
$error =
sprintf('Streaming request failed to %s', $arguments['RequestURI']);
$result = self::_StreamRequest($arguments);
if (!$result[0]) {
return $this->_HttpError($error . " " . $result[1], E_USER_WARNING);
}
self::_ReadReply();
if (!preg_match('#http/1.1 401 unauthorized#', $this->status)) {
return array(true, "success");
}
$headers = array_keys($this->reply_headers);
$error = "need authentication but no mechanism provided";
if (!in_array("www-authenticate", $headers)) {
return $this->_HttpError($error, E_USER_WARNING);
}
#$authtype = split (' ', $this->reply_headers["www-authenticate"]);
$authtype = preg_split('# #', $this->reply_headers["www-authenticate"]);
$authtype = strtolower($authtype[0]);
switch ($authtype) {
case 'basic':
$pass = base64_encode($this->user . ":" . $this->password);
$arguments["Headers"]["Authorization"] = "Basic " . $pass;
break;
case 'digest':
$arguments["Headers"]["Authorization"] = self::_BuildDigest();
break;
default:
$error =
sprintf("need '%s' authentication mechanism, but have not",
$authtype[0]);
return $this->_HttpError($error, E_USER_WARNING);
break;
}
self::Close();
self::Open($arguments);
$error = sprintf('Streaming request failed to %s after a try to authenticate', $arguments['RequestURI']);
$result = self::_StreamRequest($arguments);
if (!$result[0]) {
return $this->_HttpError($error . ": " . $result[1], E_USER_WARNING);
}
self::_ReadReply();
return array(true, "success");
}
public function ReadReplyHeaders(&$headers)
{
$headers = $this->reply_headers;
}
public function ReadReplyBody(&$body, $chunk_size)
{
$body = substr($this->reply_body, $this->last_limit, $chunk_size);
$this->last_limit += $chunk_size;
}
public function Close()
{
if (!$this->connected) {
return;
}
fclose($this->connection);
}
/*********************
*
* Private functions
*
*********************/
private function _HttpError($msg, $level, $errno = null)
{
$traceStr = '';
$backtrace = debug_backtrace();
foreach ($backtrace as $trace) {
$traceStr .= sprintf("in [file: '%s'][function: '%s'][line: %s];\n",
$trace['file'] ?? 'n/a', $trace['function'] ?? 'n/a', $trace['line'] ?? 0
);
}
$msg = sprintf('%s\n%s: [errno: %s]: %s',
$traceStr, $this->_errorToStringfunction($level), $errno, $msg);
if ($this->with_exceptions) {
throw new HttpException($msg, $errno);
}
else {
trigger_error($msg, $level);
return array(false, $msg);
}
}
private function _errorToStringfunction($value)
{
$level_names = array(
E_ERROR => 'E_ERROR',
E_WARNING => 'E_WARNING',
E_PARSE => 'E_PARSE',
E_NOTICE => 'E_NOTICE',
E_CORE_ERROR => 'E_CORE_ERROR',
E_CORE_WARNING => 'E_CORE_WARNING',
E_COMPILE_ERROR => 'E_COMPILE_ERROR',
E_COMPILE_WARNING => 'E_COMPILE_WARNING',
E_USER_ERROR => 'E_USER_ERROR',
E_USER_WARNING => 'E_USER_WARNING',
E_USER_NOTICE => 'E_USER_NOTICE',
);
if (defined('E_STRICT')) {
$level_names[E_STRICT] = 'E_STRICT';
}
$levels = array();
if (($value & E_ALL) == E_ALL) {
$levels[] = 'E_ALL';
$value &= ~E_ALL;
}
foreach ($level_names as $level => $name) {
if (($value & $level) == $level) {
$levels[] = $name;
}
}
return implode(' | ', $levels);
}
private function _streamString($string)
{
$success = fwrite($this->connection, $string);
if (!$success) {
return false;
}
return true;
}
private function _StreamRequest($arguments)
{
$this->status = false;
$this->reply_headers = array();
$this->reply_body = "";
if (!$this->connected) {
return $this->_HttpError("not connected", E_USER_WARNING);
}
$this->arguments = $arguments;
$content_length = 0;
foreach ($this->arguments["BodyStream"] as $argument) {
$type = key($argument);
$value = current($argument);
if ($type == "Data") {
$length = strlen($value);
}
elseif ($type == "File") {
if (is_readable($value)) {
$length = filesize($value);
}
else {
$length = 0;
return
$this->_HttpError(sprintf("%s: file is not readable", $value),
E_USER_WARNING);
}
}
else {
$length = 0;
return
$this->_HttpError(sprintf
("%s: not a valid argument for content", $type),
E_USER_WARNING);
}
$content_length += $length;
}
$this->request_body = sprintf("%s Bytes", $content_length);
$this->headers["Content-Length"] = $content_length;
$this->arguments["Headers"] =
array_merge($this->headers, $this->arguments["Headers"]);
if ($this->arguments["RequestMethod"] != "POST") {
return
$this->_HttpError(sprintf
("%s: method not implemented",
$arguments["RequestMethod"]), E_USER_WARNING);
}
$string =
sprintf("POST %s HTTP/1.1\r\n", $this->arguments["RequestURI"]);
$this->request_headers[$string] = '';
if (!$this->_streamString($string)) {
return $this->_HttpError("Error while puts POST operation",
E_USER_WARNING);
}
foreach ($this->arguments["Headers"] as $header => $value) {
$string = sprintf("%s: %s\r\n", $header, $value);
$this->request_headers[$header] = $value;
if (!$this->_streamString($string)) {
return $this->_HttpError("Error while puts HTTP headers",
E_USER_WARNING);
}
}
$string = "\r\n";
if (!$this->_streamString($string)) {
return $this->_HttpError("Error while ends HTTP headers",
E_USER_WARNING);
}
foreach ($this->arguments["BodyStream"] as $argument) {
$type = key($argument);
$value = current($argument);
if ($type == "Data") {
$streamed_length = 0;
while ($streamed_length < strlen($value)) {
$string = substr($value, $streamed_length, $this->window_size);
if (!$this->_streamString($string)) {
return $this->_HttpError("error while sending body data",
E_USER_WARNING);
}
$streamed_length += $this->window_size;
}
}
elseif ($type == "File") {
if (is_readable($value)) {
$file = fopen($value, 'rb');
while (!feof($file)) {
if (gettype($block = @fread($file, $this->window_size)) !=
"string"
) {
return $this->_HttpError("cannot read file to upload",
E_USER_WARNING);
}
if (!$this->_streamString($block)) {
return $this->_HttpError("error while sending body data",
E_USER_WARNING);
}
}
}
}
}
return array(true, "success");
}
private function _ReadReply()
{
if (!$this->connected) {
return array(false, "not connected");
}
$this->reply_headers = array();
$this->reply_body = "";
$headers = array();
$body = "";
while (!feof($this->connection)) {
$line = fgets($this->connection, 1024);
if (strlen(trim($line)) == 0) {
break;
} // \r\n => end of headers
if (preg_match('#^[[:space:]]#', $line)) {
$headers[-1] .= sprintf(' %s', trim($line));
continue;
}
$headers[] = trim($line);
}
$this->status = isset ($headers[0])
? strtolower($headers[0])
: false;
foreach ($headers as $header) {
$header = preg_split("#: #", $header);
$header[0] = strtolower($header[0]);
if ($header[0] !== "www-authenticate") {
$header[1] = isset ($header[1])
? strtolower($header[1])
: "";
}
if (!isset ($this->reply_headers[$header[0]])) {
$this->reply_headers[$header[0]] = $header[1];
}
}
self::_ReadStream();
return true;
}
private function _ReadStream()
{
if (!array_key_exists("content-length", $this->reply_headers)) {
stream_set_blocking($this->connection, 0);
$this->reply_body = stream_get_contents($this->connection);
return true;
}
stream_set_blocking($this->connection, 1);
$content_length = $this->reply_headers["content-length"];
$this->reply_body = stream_get_contents($this->connection, $content_length);
return true;
}
private function _BuildDigest()
{
$auth = $this->reply_headers["www-authenticate"];
#list ($head, $auth) = split (" ", $auth, 2);
list ($head, $auth) = preg_split("# #", $auth, 2);
#$auth = split (", ", $auth);
$auth = preg_split("#, #", $auth);
foreach ($auth as $sheme) {
#list ($sheme, $value) = split ('=', $sheme);
list ($sheme, $value) = preg_split('#=#', $sheme);
$fields[$sheme] = trim(trim($value), '"');
}
$nc = sprintf('%x', $this->nc);
$prepend = "";
$prependi = '';
while ((strlen($nc) + strlen($prepend)) < 8)
$prependi .= "0";
$nc = $prepend . $nc;
$cnonce = "printipp";
$username = $this->user;
$password = $this->password;
$A1 = $username . ":" . $fields["realm"] . ":" . $password;
if (array_key_exists("algorithm", $fields)) {
$algorithm = strtolower($fields["algorithm"]);
switch ($algorithm) {
case "md5":
break;
case "md5-sess":
$A1 =
$username . ":" . $fields["realm"] . ":" . $password . ":" .
$fields['nonce'] . ":" . $cnonce;
break;
default:
return $this->_HttpError(
sprintf("digest Authorization: algorithm '%s' not implemented",
$algorithm),
E_USER_WARNING);
return false;
break;
}
}
$A2 = "POST:" . $this->arguments["RequestURI"];
if (array_key_exists("qop", $fields)) {
$qop = strtolower($fields["qop"]);
#$qop = split (" ", $qop);
$qop = preg_split("# #", $qop);
if (in_array("auth", $qop)) {
$qop = "auth";
}
else {
self::_HttpError(
sprintf("digest Authorization: algorithm '%s' not implemented",
$qop),
E_USER_WARNING);
return false;
}
}
$response = md5(md5($A1) . ":" . $fields["nonce"] . ":" . md5($A2));
if (isset ($qop) && ($qop == "auth")) {
$response =
md5(md5($A1) . ":" . $fields["nonce"] . ":" . $nc . ":" . $cnonce . ":" . $qop .
":" . $A2);
}
$auth_scheme =
sprintf
('Digest username="%s", realm="%s", nonce="%s", uri="%s", response="%s"',
$username, $fields["realm"], $fields['nonce'],
$this->arguments["RequestURI"], $response);
if (isset ($algorithm)) {
$auth_scheme .= sprintf(', algorithm="%s"', $algorithm);
}
if (isset ($qop)) {
$auth_scheme .= sprintf(', cnonce="%s"', $cnonce);
}
if (array_key_exists("opaque", $fields)) {
$auth_scheme .= sprintf(', opaque="%s"', $fields['opaque']);
}
if (isset ($qop)) {
$auth_scheme .= sprintf(', qop="%s"', $qop);
}
$auth_scheme .= sprintf(', nc=%s', $nc);
$this->nc++;
return $auth_scheme;
}
}
/*
* Local variables:
* mode: php
* tab-width: 2
* c-basic-offset: 2
* End:
*/