2013-03-08 11:17:46 +01:00
< ? php
2014-12-28 11:29:53 +01:00
/* @ ( #) $Header: /sources/phpprintipp/phpprintipp/php_classes/BasicIPP.php,v 1.7 2012/03/01 17:21:04 harding Exp $
2013-03-08 11:17:46 +01:00
*
* Class BasicIPP - Send Basic IPP requests , Get and parses IPP Responses .
*
* Copyright ( C ) 2005 - 2009 Thomas HARDING
* Parts Copyright ( C ) 2005 - 2006 Manuel Lemos
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) 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
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library 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
*
* mailto : thomas . harding @ laposte . net
* Thomas Harding , 56 rue de la bourie rouge , 45 000 ORLEANS -- FRANCE
*
*/
/*
This class is intended to implement Internet Printing Protocol on client side .
References needed to debug / add functionnalities :
- RFC 2910
- RFC 2911
- RFC 3380
- RFC 3382
*/
2014-12-28 11:29:53 +01:00
2013-03-08 11:17:46 +01:00
require_once ( " http_class.php " );
2014-12-28 11:29:53 +01:00
class ippException extends \Exception
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
protected $errno ;
2015-05-30 16:14:54 +02:00
public function __construct ( $msg , $errno = null )
2014-12-28 11:29:53 +01:00
{
parent :: __construct ( $msg );
$this -> errno = $errno ;
}
2015-05-30 16:14:54 +02:00
public function getErrorFormatted ()
2014-12-28 11:29:53 +01:00
{
$return = sprintf ( " [ipp]: %s -- " . _ ( " file %s, line %s " ),
$this -> getMessage () , $this -> getFile () , $this -> getLine ());
return $return ;
}
2015-05-30 16:14:54 +02:00
public function getErrno ()
2014-12-28 11:29:53 +01:00
{
return $this -> errno ;
}
2013-03-08 11:17:46 +01:00
}
class BasicIPP
{
2014-12-28 11:29:53 +01:00
public $paths = array (
" root " => " / " ,
" admin " => " /admin/ " ,
" printers " => " /printers/ " ,
" jobs " => " /jobs/ "
);
public $http_timeout = 30 ; // timeout at http connection (seconds) 0 => default => 30.
public $http_data_timeout = 30 ; // data reading timeout (milliseconds) 0 => default => 30.
public $ssl = false ;
public $debug_level = 3 ; // max 3: almost silent
public $alert_on_end_tag ; // debugging purpose: echo "END tag OK" if (1 and reads while end tag)
2015-05-30 16:14:54 +02:00
public $with_exceptions = 1 ; // compatibility mode for old scripts // DOL_LDR_CHANGE set this to 1
2014-12-28 11:29:53 +01:00
public $handle_http_exceptions = 1 ;
// readables variables
public $jobs = array ();
public $jobs_uri = array ();
public $status = array ();
public $response_completed = array ();
public $last_job = " " ;
public $attributes ; // object you can read: attributes after validateJob()
public $printer_attributes ; // object you can read: printer's attributes after getPrinterAttributes()
public $job_attributes ; // object you can read: last job attributes
public $jobs_attributes ; // object you can read: jobs attributes after getJobs()
public $available_printers = array ();
public $printer_map = array ();
public $printers_uri = array ();
public $debug = array ();
public $response ;
public $meta ;
// protected variables;
protected $log_level = 2 ; // max 3: very verbose
protected $log_type = 3 ; // 3: file | 1: e-mail | 0: logger
protected $log_destination ; // e-mail or file
protected $serveroutput ;
protected $setup ;
protected $stringjob ;
protected $data ;
protected $debug_count = 0 ;
protected $username ;
protected $charset ;
protected $password ;
protected $requesring_user ;
protected $client_hostname = " localhost " ;
protected $stream ;
protected $host = " localhost " ;
protected $port = " 631 " ;
protected $requesting_user = '' ;
protected $printer_uri ;
protected $timeout = " 20 " ; //20 secs
protected $errNo ;
protected $errStr ;
protected $datatype ;
protected $datahead ;
protected $datatail ;
protected $operation_id ;
protected $delay ;
protected $error_generation ; //devel feature
protected $debug_http = 0 ;
protected $no_disconnect ;
protected $job_tags ;
protected $operation_tags ;
protected $index ;
protected $collection ; //RFC3382
protected $collection_index ; //RFC3382
protected $collection_key = array (); //RFC3382
protected $collection_depth = - 1 ; //RFC3382
protected $end_collection = false ; //RFC3382
protected $collection_nbr = array (); //RFC3382
protected $unix = false ; // true -> use unix sockets instead of http
protected $output ;
2015-05-30 16:14:54 +02:00
public function __construct ()
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$tz = getenv ( " date.timezone " );
if ( ! $tz )
{
$tz = @ date_default_timezone_get ();
}
date_default_timezone_set ( $tz );
$this -> meta = new \stdClass ();
$this -> setup = new \stdClass ();
$this -> values = new \stdClass ();
$this -> serveroutput = new \stdClass ();
$this -> error_generation = new \stdClass ();
$this -> _parsing = new \stdClass ();
self :: _initTags ();
2013-03-08 11:17:46 +01:00
}
2014-12-28 11:29:53 +01:00
2015-05-30 16:14:54 +02:00
public function setPort ( $port = '631' )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$this -> port = $port ;
self :: _putDebug ( " Port is " . $this -> port , 2 );
2013-03-08 11:17:46 +01:00
}
2014-12-28 11:29:53 +01:00
2015-05-30 16:14:54 +02:00
public function setUnix ( $socket = '/var/run/cups/cups.sock' )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$this -> host = $socket ;
$this -> unix = true ;
self :: _putDebug ( " Host is " . $this -> host , 2 );
2013-03-08 11:17:46 +01:00
}
2014-12-28 11:29:53 +01:00
2015-05-30 16:14:54 +02:00
public function setHost ( $host = 'localhost' )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$this -> host = $host ;
$this -> unix = false ;
self :: _putDebug ( " Host is " . $this -> host , 2 );
2013-03-08 11:17:46 +01:00
}
2014-12-28 11:29:53 +01:00
2015-05-30 16:14:54 +02:00
public function setTimeout ( $timeout )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$this -> timeout = $timeout ;
2013-03-08 11:17:46 +01:00
}
2014-12-28 11:29:53 +01:00
2015-05-30 16:14:54 +02:00
public function setPrinterURI ( $uri )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$length = strlen ( $uri );
$length = chr ( $length );
while ( strlen ( $length ) < 2 ) $length = chr ( 0x00 ) . $length ;
$this -> meta -> printer_uri = chr ( 0x45 ) // uri type | value-tag
. chr ( 0x00 ) . chr ( 0x0B ) // name-length
. " printer-uri " // printer-uri | name
. $length . $uri ;
$this -> printer_uri = $uri ;
self :: _putDebug ( sprintf ( _ ( " Printer URI: %s " ) , $uri ) , 2 );
$this -> setup -> uri = 1 ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function setData ( $data )
2014-12-28 11:29:53 +01:00
{
$this -> data = $data ;
self :: _putDebug ( " Data set " , 2 );
}
2015-05-30 16:14:54 +02:00
public function setRawText ()
2014-12-28 11:29:53 +01:00
{
$this -> setup -> datatype = 'TEXT' ;
$this -> meta -> mime_media_type = " " ;
$this -> setup -> mime_media_type = 1 ;
$this -> datahead = chr ( 0x16 );
2015-05-30 16:14:54 +02:00
if ( is_readable ( $this -> data ))
2014-12-28 11:29:53 +01:00
{
//It's a filename. Open and stream.
$data = fopen ( $this -> data , " rb " );
while ( ! feof ( $data )) $output = fread ( $data , 8192 );
}
else
{
$output = $this -> data ;
}
if ( substr ( $output , - 1 , 1 ) != chr ( 0x0c )) {
if ( ! isset ( $this -> setup -> noFormFeed ))
{
$this -> datatail = chr ( 0x0c );
}
}
self :: _putDebug ( _ ( " Forcing data to be interpreted as RAW TEXT " ) , 2 );
}
2015-05-30 16:14:54 +02:00
public function unsetRawText ()
2014-12-28 11:29:53 +01:00
{
$this -> setup -> datatype = 'BINARY' ;
$this -> datahead = '' ;
$this -> datatail = '' ;
self :: _putDebug ( _ ( " Unset forcing data to be interpreted as RAW TEXT " ) , 2 );
}
2015-05-30 16:14:54 +02:00
public function setBinary ()
2014-12-28 11:29:53 +01:00
{
self :: unsetRawText ();
}
2015-05-30 16:14:54 +02:00
public function setFormFeed ()
2014-12-28 11:29:53 +01:00
{
$this -> datatail = " \r \n " . chr ( 0x0c );
unset ( $this -> setup -> noFormFeed );
2013-03-08 11:17:46 +01:00
}
2015-05-30 16:14:54 +02:00
public function unsetFormFeed ()
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$this -> datatail = '' ;
$this -> setup -> noFormFeed = 1 ;
2013-03-08 11:17:46 +01:00
}
2014-12-28 11:29:53 +01:00
2015-05-30 16:14:54 +02:00
public function setCharset ( $charset = 'utf-8' )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$charset = strtolower ( $charset );
$this -> charset = $charset ;
$this -> meta -> charset = chr ( 0x47 ) // charset type | value-tag
. chr ( 0x00 ) . chr ( 0x12 ) // name-length
. " attributes-charset " // attributes-charset | name
. self :: _giveMeStringLength ( $charset ) // value-length
. $charset ; // value
self :: _putDebug ( sprintf ( _ ( " Charset: %s " ) , $charset ) , 2 );
$this -> setup -> charset = 1 ;
2013-03-08 11:17:46 +01:00
}
2014-12-28 11:29:53 +01:00
2015-05-30 16:14:54 +02:00
public function setLanguage ( $language = 'en_us' )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$language = strtolower ( $language );
$this -> meta -> language = chr ( 0x48 ) // natural-language type | value-tag
. chr ( 0x00 ) . chr ( 0x1B ) // name-length
. " attributes-natural-language " //attributes-natural-language
. self :: _giveMeStringLength ( $language ) // value-length
. $language ; // value
self :: _putDebug ( sprintf ( _ ( " Language: %s " ) , $language ) , 2 );
$this -> setup -> language = 1 ;
2013-03-08 11:17:46 +01:00
}
2014-12-28 11:29:53 +01:00
2015-05-30 16:14:54 +02:00
public function setDocumentFormat ( $mime_media_type = 'application/octet-stream' )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
self :: setBinary ();
$length = chr ( strlen ( $mime_media_type ));
while ( strlen ( $length ) < 2 ) $length = chr ( 0x00 ) . $length ;
self :: _putDebug ( sprintf ( _ ( " mime type: %s " ) , $mime_media_type ) , 2 );
$this -> meta -> mime_media_type = chr ( 0x49 ) // document-format tag
. self :: _giveMeStringLength ( 'document-format' ) . 'document-format' //
. self :: _giveMeStringLength ( $mime_media_type ) . $mime_media_type ; // value
$this -> setup -> mime_media_type = 1 ;
}
// setDocumentFormat alias for backward compatibility
2015-05-30 16:14:54 +02:00
public function setMimeMediaType ( $mime_media_type = " application/octet-stream " )
2014-12-28 11:29:53 +01:00
{
self :: setDocumentFormat ( $mime_media_type );
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function setCopies ( $nbrcopies = 1 )
2014-12-28 11:29:53 +01:00
{
$this -> meta -> copies = " " ;
if ( $nbrcopies == 1 || ! $nbrcopies )
{
return true ;
}
$copies = self :: _integerBuild ( $nbrcopies );
$this -> meta -> copies = chr ( 0x21 ) // integer type | value-tag
. chr ( 0x00 ) . chr ( 0x06 ) // name-length
. " copies " // copies | name
. self :: _giveMeStringLength ( $copies ) // value-length
. $copies ;
self :: _putDebug ( sprintf ( _ ( " Copies: %s " ) , $nbrcopies ) , 2 );
$this -> setup -> copies = 1 ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function setDocumentName ( $document_name = " " )
2014-12-28 11:29:53 +01:00
{
$this -> meta -> document_name = " " ;
if ( ! $document_name ) {
return true ;
}
$document_name = substr ( $document_name , 0 , 1023 );
$length = strlen ( $document_name );
$length = chr ( $length );
while ( strlen ( $length ) < 2 ) $length = chr ( 0x00 ) . $length ;
self :: _putDebug ( sprintf ( _ ( " document name: %s " ) , $document_name ) , 2 );
$this -> meta -> document_name = chr ( 0x41 ) // textWithoutLanguage tag
. chr ( 0x00 ) . chr ( 0x0d ) // name-length
. " document-name " // mimeMediaType
. self :: _giveMeStringLength ( $document_name ) . $document_name ; // value
2013-03-08 11:17:46 +01:00
}
2015-05-30 16:14:54 +02:00
public function setJobName ( $jobname = '' , $absolute = false )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$this -> meta -> jobname = '' ;
2015-05-30 16:14:54 +02:00
if ( $jobname == '' )
2014-12-28 11:29:53 +01:00
{
$this -> meta -> jobname = '' ;
return true ;
}
$postpend = date ( '-H:i:s-' ) . $this -> _setJobId ();
if ( $absolute ) {
$postpend = '' ;
}
if ( isset ( $this -> values -> jobname ) && $jobname == '(PHP)' )
{
$jobname = $this -> values -> jobname ;
}
$this -> values -> jobname = $jobname ;
$jobname .= $postpend ;
$this -> meta -> jobname = chr ( 0x42 ) // nameWithoutLanguage type || value-tag
. chr ( 0x00 ) . chr ( 0x08 ) // name-length
. " job-name " // job-name || name
. self :: _giveMeStringLength ( $jobname ) // value-length
. $jobname ; // value
self :: _putDebug ( sprintf ( _ ( " Job name: %s " ) , $jobname ) , 2 );
$this -> setup -> jobname = 1 ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function setUserName ( $username = 'PHP-SERVER' )
2014-12-28 11:29:53 +01:00
{
$this -> requesting_user = $username ;
$this -> meta -> username = '' ;
if ( ! $username ) {
return true ;
}
if ( $username == 'PHP-SERVER' && isset ( $this -> meta -> username )) {
return TRUE ;
}
/*
$value_length = 0x00 ;
2015-05-30 16:14:54 +02:00
for ( $i = 0 ; $i < strlen ( $username ); $i ++ )
2014-12-28 11:29:53 +01:00
{
$value_length += 0x01 ;
}
$value_length = chr ( $value_length );
while ( strlen ( $value_length ) < 2 ) $value_length = chr ( 0x00 ) . $value_length ;
*/
$this -> meta -> username = chr ( 0x42 ) // keyword type || value-tag
. chr ( 0x00 ) . chr ( 0x14 ) // name-length
2015-05-30 16:14:54 +02:00
. " requesting-user-name "
2014-12-28 11:29:53 +01:00
. self :: _giveMeStringLength ( $username ) // value-length
. $username ;
self :: _putDebug ( sprintf ( _ ( " Username: %s " ) , $username ) , 2 );
$this -> setup -> username = 1 ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function setAuthentification ( $username , $password )
2014-12-28 11:29:53 +01:00
{
self :: setAuthentication ( $username , $password );
2013-03-08 11:17:46 +01:00
}
2015-05-30 16:14:54 +02:00
public function setAuthentication ( $username , $password )
2013-03-08 11:17:46 +01:00
{
2014-12-28 11:29:53 +01:00
$this -> password = $password ;
$this -> username = $username ;
self :: _putDebug ( _ ( " Setting password " ) , 2 );
$this -> setup -> password = 1 ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function setSides ( $sides = 2 )
2014-12-28 11:29:53 +01:00
{
$this -> meta -> sides = '' ;
if ( ! $sides )
{
return true ;
}
2015-05-30 16:14:54 +02:00
switch ( $sides )
2014-12-28 11:29:53 +01:00
{
case 1 :
$sides = " one-sided " ;
break ;
case 2 :
$sides = " two-sided-long-edge " ;
break ;
case " 2CE " :
$sides = " two-sided-short-edge " ;
break ;
}
$this -> meta -> sides = chr ( 0x44 ) // keyword type | value-tag
. chr ( 0x00 ) . chr ( 0x05 ) // name-length
. " sides " // sides | name
. self :: _giveMeStringLength ( $sides ) // value-length
. $sides ; // one-sided | value
self :: _putDebug ( sprintf ( _ ( " Sides value set to %s " ) , $sides ) , 2 );
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function setFidelity ()
2014-12-28 11:29:53 +01:00
{
// whether the server can't replace any attributes
// (eg, 2 sided print is not possible,
// so print one sided) and DO NOT THE JOB.
$this -> meta -> fidelity = chr ( 0x22 ) // boolean type | value-tag
. chr ( 0x00 ) . chr ( 0x16 ) // name-length
. " ipp-attribute-fidelity " // ipp-attribute-fidelity | name
. chr ( 0x00 ) . chr ( 0x01 ) // value-length
. chr ( 0x01 ); // true | value
self :: _putDebug ( _ ( " Fidelity attribute is set (paranoid mode) " ) , 3 );
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function unsetFidelity ()
2014-12-28 11:29:53 +01:00
{
// whether the server can replace any attributes
// (eg, 2 sided print is not possible,
// so print one sided) and DO THE JOB.
$this -> meta -> fidelity = chr ( 0x22 ) // boolean type | value-tag
. chr ( 0x00 ) . chr ( 0x16 ) // name-length
. " ipp-attribute-fidelity " // ipp-attribute-fidelity | name
. chr ( 0x00 ) . chr ( 0x01 ) // value-length
. chr ( 0x00 ); // false | value
self :: _putDebug ( _ ( " Fidelity attribute is unset " ) , 2 );
}
2013-03-08 11:17:46 +01:00
2014-12-28 11:29:53 +01:00
public function setMessage ( $message = '' )
{
$this -> meta -> message = '' ;
if ( ! $message ) {
return true ;
}
2015-05-30 16:14:54 +02:00
$this -> meta -> message =
2014-12-28 11:29:53 +01:00
chr ( 0x41 ) // attribute type = textWithoutLanguage
2015-05-30 16:14:54 +02:00
. chr ( 0x00 )
. chr ( 0x07 )
. " message "
2014-12-28 11:29:53 +01:00
. self :: _giveMeStringLength ( substr ( $message , 0 , 127 ))
. substr ( $message , 0 , 127 );
self :: _putDebug ( sprintf ( _ ( 'Setting message to "%s"' ) , $message ) , 2 );
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function setPageRanges ( $page_ranges )
2014-12-28 11:29:53 +01:00
{
// $pages_ranges = string: "1:5 10:25 40:52 ..."
// to unset, specify an empty string.
$this -> meta -> page_range = '' ;
if ( ! $page_ranges ) {
return true ;
}
$page_ranges = trim ( str_replace ( " - " , " : " , $page_ranges ));
$first = true ;
#$page_ranges = split(' ', $page_ranges);
$page_ranges = preg_split ( '# #' , $page_ranges );
2015-05-30 16:14:54 +02:00
foreach ( $page_ranges as $page_range )
2014-12-28 11:29:53 +01:00
{
$value = self :: _rangeOfIntegerBuild ( $page_range );
if ( $first )
{
2015-05-30 16:14:54 +02:00
$this -> meta -> page_ranges .=
$this -> tags_types [ 'rangeOfInteger' ][ 'tag' ]
. self :: _giveMeStringLength ( 'page-ranges' )
. 'page-ranges'
. self :: _giveMeStringLength ( $value )
2014-12-28 11:29:53 +01:00
. $value ;
}
else
{
2015-05-30 16:14:54 +02:00
$this -> meta -> page_ranges .=
$this -> tags_types [ 'rangeOfInteger' ][ 'tag' ]
. self :: _giveMeStringLength ( '' )
. self :: _giveMeStringLength ( $value )
2014-12-28 11:29:53 +01:00
. $value ;
$first = false ;
}
}
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function setAttribute ( $attribute , $values )
2014-12-28 11:29:53 +01:00
{
$operation_attributes_tags = array_keys ( $this -> operation_tags );
$job_attributes_tags = array_keys ( $this -> job_tags );
$printer_attributes_tags = array_keys ( $this -> printer_tags );
self :: unsetAttribute ( $attribute );
2015-05-30 16:14:54 +02:00
if ( in_array ( $attribute , $operation_attributes_tags ))
2014-12-28 11:29:53 +01:00
{
if ( ! is_array ( $values ))
{
self :: _setOperationAttribute ( $attribute , $values );
}
else
{
foreach ( $values as $value )
{
self :: _setOperationAttribute ( $attribute , $value );
}
}
}
2015-05-30 16:14:54 +02:00
elseif ( in_array ( $attribute , $job_attributes_tags ))
2014-12-28 11:29:53 +01:00
{
if ( ! is_array ( $values ))
{
self :: _setJobAttribute ( $attribute , $values );
}
2015-05-30 16:14:54 +02:00
else
2014-12-28 11:29:53 +01:00
{
foreach ( $values as $value )
{
self :: _setJobAttribute ( $attribute , $value );
}
}
}
2015-05-30 16:14:54 +02:00
elseif ( in_array ( $attribute , $printer_attributes_tags ))
2014-12-28 11:29:53 +01:00
{
if ( ! is_array ( $values ))
{
self :: _setPrinterAttribute ( $attribute , $values );
}
else
{
foreach ( $values as $value )
{
self :: _setPrinterAttribute ( $attribute , $value );
}
}
}
else
{
trigger_error (
sprintf ( _ ( 'SetAttribute: Tag "%s" is not a printer or a job attribute' ),
$attribute ) , E_USER_NOTICE );
self :: _putDebug (
sprintf ( _ ( 'SetAttribute: Tag "%s" is not a printer or a job attribute' ),
$attribute ) , 3 );
self :: _errorLog (
sprintf ( _ ( 'SetAttribute: Tag "%s" is not a printer or a job attribute' ),
$attribute ) , 2 );
return FALSE ;
}
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
public function unsetAttribute ( $attribute )
2014-12-28 11:29:53 +01:00
{
$operation_attributes_tags = array_keys ( $this -> operation_tags );
$job_attributes_tags = array_keys ( $this -> job_tags );
$printer_attributes_tags = array_keys ( $this -> printer_tags );
2015-05-30 16:14:54 +02:00
if ( in_array ( $attribute , $operation_attributes_tags ))
2014-12-28 11:29:53 +01:00
{
2015-05-30 16:14:54 +02:00
unset (
2014-12-28 11:29:53 +01:00
$this -> operation_tags [ $attribute ][ 'value' ],
$this -> operation_tags [ $attribute ][ 'systag' ]
);
}
elseif ( in_array ( $attribute , $job_attributes_tags ))
{
unset (
$this -> job_tags [ $attribute ][ 'value' ],
$this -> job_tags [ $attribute ][ 'systag' ]
);
}
elseif ( in_array ( $attribute , $printer_attributes_tags ))
{
unset (
$this -> printer_tags [ $attribute ][ 'value' ],
$this -> printer_tags [ $attribute ][ 'systag' ]
);
}
2015-05-30 16:14:54 +02:00
else
2014-12-28 11:29:53 +01:00
{
trigger_error (
sprintf ( _ ( 'unsetAttribute: Tag "%s" is not a printer or a job attribute' ),
$attribute ) , E_USER_NOTICE );
self :: _putDebug (
sprintf ( _ ( 'unsetAttribute: Tag "%s" is not a printer or a job attribute' ),
$attribute ) , 3 );
self :: _errorLog (
sprintf ( _ ( 'unsetAttribute: Tag "%s" is not a printer or a job attribute' ),
$attribute ) , 2 );
return FALSE ;
}
return true ;
}
//
// LOGGING / DEBUGGING
//
/**
* Sets log file destination . Creates the file if has permission .
*
* @ param string $log_destination
* @ param string $destination_type
* @ param int $level
*
* @ throws ippException
*/
2015-05-30 16:14:54 +02:00
public function setLog ( $log_destination , $destination_type = 'file' , $level = 2 )
2014-12-28 11:29:53 +01:00
{
if ( ! file_exists ( $log_destination ) && is_writable ( dirname ( $log_destination )))
{
touch ( $log_destination );
chmod ( $log_destination , 0777 );
}
2015-05-30 16:14:54 +02:00
switch ( $destination_type )
2014-12-28 11:29:53 +01:00
{
case 'file' :
case 3 :
$this -> log_destination = $log_destination ;
$this -> log_type = 3 ;
break ;
case 'logger' :
case 0 :
$this -> log_destination = '' ;
$this -> log_type = 0 ;
break ;
case 'e-mail' :
case 1 :
$this -> log_destination = $log_destination ;
$this -> log_type = 1 ;
break ;
}
$this -> log_level = $level ;
}
2015-05-30 16:14:54 +02:00
public function printDebug ()
2014-12-28 11:29:53 +01:00
{
for ( $i = 0 ; $i < $this -> debug_count ; $i ++ )
{
echo $this -> debug [ $i ], " \n " ;
}
$this -> debug = array ();
$this -> debug_count = 0 ;
}
2015-05-30 16:14:54 +02:00
public function getDebug ()
2014-12-28 11:29:53 +01:00
{
$debug = '' ;
for ( $i = 0 ; $i < $this -> debug_count ; $i ++ )
{
$debug .= $this -> debug [ $i ];
}
$this -> debug = array ();
$this -> debug_count = 0 ;
return $debug ;
}
//
// OPERATIONS
//
2015-05-30 16:14:54 +02:00
public function printJob ()
2014-12-28 11:29:53 +01:00
{
// this BASIC version of printJob do not parse server
// output for job's attributes
self :: _putDebug (
sprintf (
" ************** Date: %s *********** " ,
date ( 'Y-m-d H:i:s' )
)
);
if ( ! $this -> _stringJob ()) {
return FALSE ;
}
2015-05-30 16:14:54 +02:00
if ( is_readable ( $this -> data ))
2014-12-28 11:29:53 +01:00
{
self :: _putDebug ( _ ( " Printing a FILE " ));
$this -> output = $this -> stringjob ;
if ( $this -> setup -> datatype == " TEXT " )
{
$this -> output .= chr ( 0x16 );
}
$post_values = array (
" Content-Type " => " application/ipp " ,
" Data " => $this -> output ,
" File " => $this -> data
);
if ( $this -> setup -> datatype == " TEXT " && ! isset ( $this -> setup -> noFormFeed ))
{
$post_values = array_merge (
$post_values ,
array (
" Filetype " => " TEXT "
)
);
}
}
else
{
self :: _putDebug ( _ ( " Printing DATA " ));
2015-05-30 16:14:54 +02:00
$this -> output =
2014-12-28 11:29:53 +01:00
$this -> stringjob
. $this -> datahead
. $this -> data
. $this -> datatail ;
$post_values = array (
" Content-Type " => " application/ipp " ,
" Data " => $this -> output
);
}
if ( self :: _sendHttp ( $post_values , $this -> paths [ " printers " ]))
{
self :: _parseServerOutput ();
}
2015-05-30 16:14:54 +02:00
if ( isset ( $this -> serveroutput ) && isset ( $this -> serveroutput -> status ))
2014-12-28 11:29:53 +01:00
{
$this -> status = array_merge ( $this -> status , array (
$this -> serveroutput -> status
));
if ( $this -> serveroutput -> status == " successfull-ok " )
{
self :: _errorLog (
2015-05-30 16:14:54 +02:00
sprintf ( " printing job %s: " , $this -> last_job )
2014-12-28 11:29:53 +01:00
. $this -> serveroutput -> status ,
3 );
}
else
{
self :: _errorLog (
2015-05-30 16:14:54 +02:00
sprintf ( " printing job: " , $this -> last_job )
2014-12-28 11:29:53 +01:00
. $this -> serveroutput -> status ,
1 );
}
return $this -> serveroutput -> status ;
}
2015-05-30 16:14:54 +02:00
$this -> status =
2014-12-28 11:29:53 +01:00
array_merge ( $this -> status , array ( " OPERATION FAILED " ));
2015-05-30 16:14:54 +02:00
$this -> jobs =
2014-12-28 11:29:53 +01:00
array_merge ( $this -> jobs , array ( " " ));
2015-05-30 16:14:54 +02:00
$this -> jobs_uri =
2014-12-28 11:29:53 +01:00
array_merge ( $this -> jobs_uri , array ( " " ));
self :: _errorLog ( " printing job : OPERATION FAILED " , 1 );
return false ;
}
//
// HTTP OUTPUT
//
2015-05-30 16:14:54 +02:00
protected function _sendHttp ( $post_values , $uri )
2014-12-28 11:29:53 +01:00
{
/*
This function Copyright ( C ) 2005 - 2006 Thomas Harding , Manuel Lemos
*/
$this -> response_completed [] = " no " ;
unset ( $this -> serverouptut );
self :: _putDebug ( _ ( " Processing HTTP request " ) , 2 );
$this -> serveroutput -> headers = array ();
$this -> serveroutput -> body = " " ;
$http = new http_class ;
if ( ! $this -> unix ) {
2015-05-30 16:14:54 +02:00
// DOL_LDR_CHANGE
if ( empty ( $this -> host )) $this -> host = '127.0.0.1' ;
2014-12-28 11:29:53 +01:00
$http -> host = $this -> host ;
}
else {
$http -> host = " localhost " ;
}
$http -> with_exceptions = $this -> with_exceptions ;
2015-05-30 16:14:54 +02:00
if ( $this -> debug_http )
2014-12-28 11:29:53 +01:00
{
$http -> debug = 1 ;
$http -> html_debug = 0 ;
}
else
{
$http -> debug = 0 ;
$http -> html_debug = 0 ;
}
$url = " http:// " . $this -> host ;
if ( $this -> ssl ) {
$url = " https:// " . $this -> host ;
}
if ( $this -> unix ) {
$url = " unix:// " . $this -> host ;
}
$http -> port = $this -> port ;
$http -> timeout = $this -> http_timeout ;
$http -> data_timeout = $this -> http_data_timeout ;
$http -> force_multipart_form_post = false ;
$http -> user = $this -> username ;
$http -> password = $this -> password ;
$error = $http -> GetRequestArguments ( $url , $arguments );
$arguments [ " RequestMethod " ] = " POST " ;
$arguments [ " Headers " ] = array (
" Content-Type " => " application/ipp "
);
$arguments [ " BodyStream " ] = array (
array (
" Data " => $post_values [ " Data " ]
)
);
if ( isset ( $post_values [ " File " ])) {
$arguments [ " BodyStream " ][] = array (
" File " => $post_values [ " File " ]
);
}
2015-05-30 16:14:54 +02:00
if ( isset ( $post_values [ " FileType " ])
2014-12-28 11:29:53 +01:00
&& ! strcmp ( $post_values [ " FileType " ], " TEXT " )
)
{
$arguments [ " BodyStream " ][] = array ( " Data " => Chr ( 12 ));
}
$arguments [ " RequestURI " ] = $uri ;
2015-05-30 16:14:54 +02:00
if ( $this -> with_exceptions && $this -> handle_http_exceptions )
2014-12-28 11:29:53 +01:00
{
try
{
$success = $http -> Open ( $arguments );
}
2015-05-30 16:14:54 +02:00
catch ( httpException $e )
2014-12-28 11:29:53 +01:00
{
throw new ippException (
sprintf ( " http error: %s " , $e -> getMessage ()),
$e -> getErrno ());
}
}
else
{
2015-05-30 16:14:54 +02:00
$success = $http -> Open ( $arguments );
2014-12-28 11:29:53 +01:00
}
2015-05-30 16:14:54 +02:00
if ( $success [ 0 ] == true )
2014-12-28 11:29:53 +01:00
{
$success = $http -> SendRequest ( $arguments );
2015-05-30 16:14:54 +02:00
if ( $success [ 0 ] == true )
2014-12-28 11:29:53 +01:00
{
self :: _putDebug ( " H T T P R E Q U E S T : " );
self :: _putDebug ( " Request headers: " );
2015-05-30 16:14:54 +02:00
for ( Reset ( $http -> request_headers ) , $header = 0 ; $header < count ( $http -> request_headers ); Next ( $http -> request_headers ) , $header ++ )
2014-12-28 11:29:53 +01:00
{
$header_name = Key ( $http -> request_headers );
2015-05-30 16:14:54 +02:00
if ( GetType ( $http -> request_headers [ $header_name ]) == " array " )
2014-12-28 11:29:53 +01:00
{
for ( $header_value = 0 ; $header_value < count ( $http -> request_headers [ $header_name ]); $header_value ++ )
{
self :: _putDebug ( $header_name . " : " . $http -> request_headers [ $header_name ][ $header_value ]);
}
}
else
{
self :: _putDebug ( $header_name . " : " . $http -> request_headers [ $header_name ]);
}
}
self :: _putDebug ( " Request body: " );
self :: _putDebug (
2015-05-30 16:14:54 +02:00
htmlspecialchars ( $http -> request_body )
2014-12-28 11:29:53 +01:00
. " *********** END REQUEST BODY ********* "
);
$i = 0 ;
$headers = array ();
unset ( $this -> serveroutput -> headers );
$http -> ReadReplyHeaders ( $headers );
self :: _putDebug ( " H T T P R E S P O N S E : " );
self :: _putDebug ( " Response headers: " );
2015-05-30 16:14:54 +02:00
for ( Reset ( $headers ) , $header = 0 ; $header < count ( $headers ); Next ( $headers ) , $header ++ )
2014-12-28 11:29:53 +01:00
{
$header_name = Key ( $headers );
2015-05-30 16:14:54 +02:00
if ( GetType ( $headers [ $header_name ]) == " array " )
2014-12-28 11:29:53 +01:00
{
2015-05-30 16:14:54 +02:00
for ( $header_value = 0 ; $header_value < count ( $headers [ $header_name ]); $header_value ++ )
2014-12-28 11:29:53 +01:00
{
self :: _putDebug ( $header_name . " : " . $headers [ $header_name ][ $header_value ]);
2015-05-30 16:14:54 +02:00
$this -> serveroutput -> headers [ $i ] =
$header_name . " : "
2014-12-28 11:29:53 +01:00
. $headers [ $header_name ][ $header_value ];
$i ++ ;
}
}
else
{
self :: _putDebug ( $header_name . " : " . $headers [ $header_name ]);
2015-05-30 16:14:54 +02:00
$this -> serveroutput -> headers [ $i ] =
$header_name
. " : "
2014-12-28 11:29:53 +01:00
. $headers [ $header_name ];
$i ++ ;
}
}
self :: _putDebug ( " \n \n Response body: \n " );
$this -> serveroutput -> body = " " ;
2015-05-30 16:14:54 +02:00
for (;;)
2014-12-28 11:29:53 +01:00
{
$http -> ReadReplyBody ( $body , 1024 );
if ( strlen ( $body ) == 0 ) {
break ;
}
self :: _putDebug ( htmlentities ( $body ));
$this -> serveroutput -> body .= $body ;
}
self :: _putDebug ( " ********* END RESPONSE BODY ******** " );
}
}
$http -> Close ();
return true ;
}
2013-03-08 11:17:46 +01:00
2014-12-28 11:29:53 +01:00
//
// INIT
//
2015-05-30 16:14:54 +02:00
protected function _initTags ()
2014-12-28 11:29:53 +01:00
{
$this -> tags_types = array (
" unsupported " => array (
" tag " => chr ( 0x10 ) ,
" build " => " "
) ,
" reserved " => array (
" tag " => chr ( 0x11 ) ,
" build " => " "
) ,
" unknown " => array (
" tag " => chr ( 0x12 ) ,
" build " => " "
) ,
" no-value " => array (
" tag " => chr ( 0x13 ) ,
" build " => " no_value "
) ,
" integer " => array (
" tag " => chr ( 0x21 ) ,
" build " => " integer "
) ,
" boolean " => array (
" tag " => chr ( 0x22 ) ,
" build " => " boolean "
) ,
" enum " => array (
" tag " => chr ( 0x23 ) ,
" build " => " enum "
) ,
" octetString " => array (
" tag " => chr ( 0x30 ) ,
" build " => " octet_string "
) ,
" datetime " => array (
" tag " => chr ( 0x31 ) ,
" build " => " datetime "
) ,
" resolution " => array (
" tag " => chr ( 0x32 ) ,
" build " => " resolution "
) ,
" rangeOfInteger " => array (
" tag " => chr ( 0x33 ) ,
" build " => " range_of_integers "
) ,
" textWithLanguage " => array (
" tag " => chr ( 0x35 ) ,
" build " => " string "
) ,
" nameWithLanguage " => array (
" tag " => chr ( 0x36 ) ,
" build " => " string "
) ,
/*
" text " => array ( " tag " => chr ( 0x40 ),
" build " => " string " ),
" text string " => array ( " tag " => chr ( 0x40 ),
" build " => " string " ),
*/
" textWithoutLanguage " => array (
" tag " => chr ( 0x41 ) ,
" build " => " string "
) ,
" nameWithoutLanguage " => array (
" tag " => chr ( 0x42 ) ,
" buid " => " string "
) ,
" keyword " => array (
" tag " => chr ( 0x44 ) ,
" build " => " string "
) ,
" uri " => array (
" tag " => chr ( 0x45 ) ,
" build " => " string "
) ,
" uriScheme " => array (
" tag " => chr ( 0x46 ) ,
" build " => " string "
) ,
" charset " => array (
" tag " => chr ( 0x47 ) ,
" build " => " string "
) ,
" naturalLanguage " => array (
" tag " => chr ( 0x48 ) ,
" build " => " string "
) ,
" mimeMediaType " => array (
" tag " => chr ( 0x49 ) ,
" build " => " string "
) ,
" extendedAttributes " => array (
" tag " => chr ( 0x7F ) ,
" build " => " extended "
) ,
);
$this -> operation_tags = array (
" compression " => array (
" tag " => " keyword "
) ,
" document-natural-language " => array (
" tag " => " naturalLanguage "
) ,
" job-k-octets " => array (
" tag " => " integer "
) ,
" job-impressions " => array (
" tag " => " integer "
) ,
" job-media-sheets " => array (
" tag " => " integer "
) ,
);
$this -> job_tags = array (
" job-priority " => array (
" tag " => " integer "
) ,
" job-hold-until " => array (
" tag " => " keyword "
) ,
" job-sheets " => array (
" tag " => " keyword "
) , //banner page
" multiple-document-handling " => array (
" tag " => " keyword "
) ,
//"copies" => array("tag" => "integer"),
" finishings " => array (
" tag " => " enum "
) ,
//"page-ranges" => array("tag" => "rangeOfInteger"), // has its own function
//"sides" => array("tag" => "keyword"), // has its own function
" number-up " => array (
" tag " => " integer "
) ,
" orientation-requested " => array (
" tag " => " enum "
) ,
" media " => array (
" tag " => " keyword "
) ,
" printer-resolution " => array (
" tag " => " resolution "
) ,
" print-quality " => array (
" tag " => " enum "
) ,
" job-message-from-operator " => array (
" tag " => " textWithoutLanguage "
) ,
);
$this -> printer_tags = array (
" requested-attributes " => array (
" tag " => " keyword "
)
);
}
2013-03-08 11:17:46 +01:00
2014-12-28 11:29:53 +01:00
//
// SETUP
//
2015-05-30 16:14:54 +02:00
protected function _setOperationId ()
2014-12-28 11:29:53 +01:00
{
$prepend = '' ;
$this -> operation_id += 1 ;
$this -> meta -> operation_id = self :: _integerBuild ( $this -> operation_id );
self :: _putDebug ( " operation id is: " . $this -> operation_id , 2 );
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
protected function _setJobId ()
2014-12-28 11:29:53 +01:00
{
$this -> meta -> jobid += 1 ;
$prepend = '' ;
$prepend_length = 4 - strlen ( $this -> meta -> jobid );
for ( $i = 0 ; $i < $prepend_length ; $i ++ ) {
$prepend .= '0' ;
}
return $prepend . $this -> meta -> jobid ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
protected function _setJobUri ( $job_uri )
2014-12-28 11:29:53 +01:00
{
$this -> meta -> job_uri = chr ( 0x45 ) // type uri
. chr ( 0x00 ) . chr ( 0x07 ) // name-length
. " job-uri "
//. chr(0x00).chr(strlen($job_uri))
. self :: _giveMeStringLength ( $job_uri ) . $job_uri ;
self :: _putDebug ( " job-uri is: " . $job_uri , 2 );
}
2013-03-08 11:17:46 +01:00
2014-12-28 11:29:53 +01:00
//
// RESPONSE PARSING
//
2015-05-30 16:14:54 +02:00
protected function _parseServerOutput ()
2014-12-28 11:29:53 +01:00
{
$this -> serveroutput -> response = array ();
if ( ! self :: _parseHttpHeaders ()) {
return FALSE ;
}
$this -> _parsing -> offset = 0 ;
self :: _parseIppVersion ();
self :: _parseStatusCode ();
self :: _parseRequestID ();
$this -> _parseResponse ();
//devel
self :: _putDebug (
sprintf ( " ***** IPP STATUS: %s ****** " , $this -> serveroutput -> status ),
4 );
self :: _putDebug ( " ****** END OF OPERATION **** " );
return true ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
protected function _parseHttpHeaders ()
2014-12-28 11:29:53 +01:00
{
$response = " " ;
2015-05-30 16:14:54 +02:00
switch ( $this -> serveroutput -> headers [ 0 ])
2014-12-28 11:29:53 +01:00
{
case " http/1.1 200 ok: " :
$this -> serveroutput -> httpstatus = " HTTP/1.1 200 OK " ;
$response = " OK " ;
break ;
// primitive http/1.0 for Lexmark printers (from Rick Baril)
case " http/1.0 200 ok: " :
$this -> serveroutput -> httpstatus = " HTTP/1.0 200 OK " ;
$response = " OK " ;
break ;
case " http/1.1 100 continue: " :
$this -> serveroutput -> httpstatus = " HTTP/1.1 100 CONTINUE " ;
$response = " OK " ;
break ;
case " " :
$this -> serveroutput -> httpstatus = " HTTP/1.1 000 No Response From Server " ;
$this -> serveroutput -> status = " HTTP-ERROR-000_NO_RESPONSE_FROM_SERVER " ;
trigger_error ( " No Response From Server " , E_USER_WARNING );
self :: _errorLog ( " No Response From Server " , 1 );
$this -> disconnected = 1 ;
return FALSE ;
break ;
default :
$server_response = preg_replace ( " /: $ / " , '' , $this -> serveroutput -> headers [ 0 ]);
#$strings = split(' ', $server_response, 3);
$strings = preg_split ( '# #' , $server_response , 3 );
$errno = $strings [ 1 ];
$string = strtoupper ( str_replace ( ' ' , '_' , $strings [ 2 ]));
trigger_error (
sprintf ( _ ( " server responds %s " ) , $server_response ),
E_USER_WARNING );
self :: _errorLog ( " server responds " . $server_response , 1 );
$this -> serveroutput -> httpstatus =
strtoupper ( $strings [ 0 ])
. " "
. $errno
. " "
. ucfirst ( $strings [ 2 ]);
$this -> serveroutput -> status =
" HTTP-ERROR- "
. $errno
. " - "
. $string ;
$this -> disconnected = 1 ;
return FALSE ;
break ;
}
unset ( $this -> serveroutput -> headers );
return TRUE ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
protected function _parseIppVersion ()
2014-12-28 11:29:53 +01:00
{
$ippversion =
( ord ( $this -> serveroutput -> body [ $this -> _parsing -> offset ]) * 256 )
+ ord ( $this -> serveroutput -> body [ $this -> _parsing -> offset + 1 ]);
2015-05-30 16:14:54 +02:00
switch ( $ippversion )
2014-12-28 11:29:53 +01:00
{
case 0x0101 :
$this -> serveroutput -> ipp_version = " 1.1 " ;
break ;
default :
$this -> serveroutput -> ipp_version =
sprintf ( " %u.%u (Unknown) " ,
ord ( $this -> serveroutput -> body [ $this -> _parsing -> offset ]) * 256 ,
ord ( $this -> serveroutput -> body [ $this -> _parsing -> offset + 1 ]));
break ;
}
self :: _putDebug ( " I P P R E S P O N S E : \n \n " );
self :: _putDebug (
sprintf ( " IPP version %s%s: %s " ,
ord ( $this -> serveroutput -> body [ $this -> _parsing -> offset ]),
ord ( $this -> serveroutput -> body [ $this -> _parsing -> offset + 1 ]),
$this -> serveroutput -> ipp_version ));
$this -> _parsing -> offset += 2 ;
return ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
protected function _parseStatusCode ()
2014-12-28 11:29:53 +01:00
{
$status_code =
( ord ( $this -> serveroutput -> body [ $this -> _parsing -> offset ]) * 256 )
+ ord ( $this -> serveroutput -> body [ $this -> _parsing -> offset + 1 ]);
$this -> serveroutput -> status = " NOT PARSED " ;
$this -> _parsing -> offset += 2 ;
if ( strlen ( $this -> serveroutput -> body ) < $this -> _parsing -> offset )
{
return false ;
}
2015-05-30 16:14:54 +02:00
if ( $status_code < 0x00FF )
2014-12-28 11:29:53 +01:00
{
$this -> serveroutput -> status = " successfull " ;
}
2015-05-30 16:14:54 +02:00
elseif ( $status_code < 0x01FF )
2014-12-28 11:29:53 +01:00
{
$this -> serveroutput -> status = " informational " ;
}
2015-05-30 16:14:54 +02:00
elseif ( $status_code < 0x02FF )
2014-12-28 11:29:53 +01:00
{
$this -> serveroutput -> status = " redirection " ;
}
2015-05-30 16:14:54 +02:00
elseif ( $status_code < 0x04FF )
2014-12-28 11:29:53 +01:00
{
$this -> serveroutput -> status = " client-error " ;
}
2015-05-30 16:14:54 +02:00
elseif ( $status_code < 0x05FF )
2014-12-28 11:29:53 +01:00
{
$this -> serveroutput -> status = " server-error " ;
}
2015-05-30 16:14:54 +02:00
switch ( $status_code )
2014-12-28 11:29:53 +01:00
{
case 0x0000 :
$this -> serveroutput -> status = " successfull-ok " ;
break ;
case 0x0001 :
$this -> serveroutput -> status = " successful-ok-ignored-or-substituted-attributes " ;
break ;
case 0x002 :
$this -> serveroutput -> status = " successful-ok-conflicting-attributes " ;
break ;
case 0x0400 :
$this -> serveroutput -> status = " client-error-bad-request " ;
break ;
case 0x0401 :
$this -> serveroutput -> status = " client-error-forbidden " ;
break ;
case 0x0402 :
$this -> serveroutput -> status = " client-error-not-authenticated " ;
break ;
case 0x0403 :
$this -> serveroutput -> status = " client-error-not-authorized " ;
break ;
case 0x0404 :
$this -> serveroutput -> status = " client-error-not-possible " ;
break ;
case 0x0405 :
$this -> serveroutput -> status = " client-error-timeout " ;
break ;
case 0x0406 :
$this -> serveroutput -> status = " client-error-not-found " ;
break ;
case 0x0407 :
$this -> serveroutput -> status = " client-error-gone " ;
break ;
case 0x0408 :
$this -> serveroutput -> status = " client-error-request-entity-too-large " ;
break ;
case 0x0409 :
$this -> serveroutput -> status = " client-error-request-value-too-long " ;
break ;
case 0x040A :
$this -> serveroutput -> status = " client-error-document-format-not-supported " ;
break ;
case 0x040B :
$this -> serveroutput -> status = " client-error-attributes-or-values-not-supported " ;
break ;
case 0x040C :
$this -> serveroutput -> status = " client-error-uri-scheme-not-supported " ;
break ;
case 0x040D :
$this -> serveroutput -> status = " client-error-charset-not-supported " ;
break ;
case 0x040E :
$this -> serveroutput -> status = " client-error-conflicting-attributes " ;
break ;
case 0x040F :
$this -> serveroutput -> status = " client-error-compression-not-supported " ;
break ;
case 0x0410 :
$this -> serveroutput -> status = " client-error-compression-error " ;
break ;
case 0x0411 :
$this -> serveroutput -> status = " client-error-document-format-error " ;
break ;
case 0x0412 :
$this -> serveroutput -> status = " client-error-document-access-error " ;
break ;
case 0x0413 : // RFC3380
$this -> serveroutput -> status = " client-error-attributes-not-settable " ;
break ;
case 0x0500 :
$this -> serveroutput -> status = " server-error-internal-error " ;
break ;
case 0x0501 :
$this -> serveroutput -> status = " server-error-operation-not-supported " ;
break ;
case 0x0502 :
$this -> serveroutput -> status = " server-error-service-unavailable " ;
break ;
case 0x0503 :
$this -> serveroutput -> status = " server-error-version-not-supported " ;
break ;
case 0x0504 :
$this -> serveroutput -> status = " server-error-device-error " ;
break ;
case 0x0505 :
$this -> serveroutput -> status = " server-error-temporary-error " ;
break ;
case 0x0506 :
$this -> serveroutput -> status = " server-error-not-accepting-jobs " ;
break ;
case 0x0507 :
$this -> serveroutput -> status = " server-error-busy " ;
break ;
case 0x0508 :
$this -> serveroutput -> status = " server-error-job-canceled " ;
break ;
case 0x0509 :
$this -> serveroutput -> status = " server-error-multiple-document-jobs-not-supported " ;
break ;
default :
break ;
}
self :: _putDebug (
sprintf (
" status-code: %s%s: %s " ,
$this -> serveroutput -> body [ $this -> _parsing -> offset ],
$this -> serveroutput -> body [ $this -> _parsing -> offset + 1 ],
$this -> serveroutput -> status ),
4 );
return ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
protected function _parseRequestID ()
2014-12-28 11:29:53 +01:00
{
$this -> serveroutput -> request_id =
self :: _interpretInteger (
substr ( $this -> serveroutput -> body , $this -> _parsing -> offset , 4 )
);
self :: _putDebug ( " request-id " . $this -> serveroutput -> request_id , 2 );
$this -> _parsing -> offset += 4 ;
return ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
protected function _interpretInteger ( $value )
2014-12-28 11:29:53 +01:00
{
// they are _signed_ integers
$value_parsed = 0 ;
for ( $i = strlen ( $value ); $i > 0 ; $i -- )
{
$value_parsed +=
(
2015-05-30 16:14:54 +02:00
( 1 << (( $i - 1 ) * 8 ))
*
2014-12-28 11:29:53 +01:00
ord ( $value [ strlen ( $value ) - $i ])
);
}
if ( $value_parsed >= 2147483648 )
{
$value_parsed -= 4294967296 ;
}
return $value_parsed ;
}
2013-03-08 11:17:46 +01:00
2015-05-30 16:14:54 +02:00
protected function _parseResponse ()
2014-12-28 11:29:53 +01:00
{
2013-03-08 11:17:46 +01:00
}
2014-12-28 11:29:53 +01:00
//
// REQUEST BUILDING
//
2015-05-30 16:14:54 +02:00
protected function _stringJob ()
2014-12-28 11:29:53 +01:00
{
if ( ! isset ( $this -> setup -> charset )) {
self :: setCharset ();
}
if ( ! isset ( $this -> setup -> datatype )) {
self :: setBinary ();
}
2015-05-30 16:14:54 +02:00
if ( ! isset ( $this -> setup -> uri ))
2014-12-28 11:29:53 +01:00
{
$this -> getPrinters ();
unset ( $this -> jobs [ count ( $this -> jobs ) - 1 ]);
unset ( $this -> jobs_uri [ count ( $this -> jobs_uri ) - 1 ]);
unset ( $this -> status [ count ( $this -> status ) - 1 ]);
if ( array_key_exists ( 0 , $this -> available_printers ))
{
self :: setPrinterURI ( $this -> available_printers [ 0 ]);
}
2015-05-30 16:14:54 +02:00
else
2014-12-28 11:29:53 +01:00
{
trigger_error (
_ ( " _stringJob: Printer URI is not set: die " ),
E_USER_WARNING );
self :: _putDebug ( _ ( " _stringJob: Printer URI is not set: die " ) , 4 );
self :: _errorLog ( " Printer URI is not set, die " , 2 );
return FALSE ;
}
}
if ( ! isset ( $this -> setup -> copies )) {
self :: setCopies ( 1 );
}
if ( ! isset ( $this -> setup -> language )) {
self :: setLanguage ( 'en_us' );
}
if ( ! isset ( $this -> setup -> mime_media_type )) {
self :: setMimeMediaType ();
}
if ( ! isset ( $this -> setup -> jobname )) {
self :: setJobName ();
}
unset ( $this -> setup -> jobname );
if ( ! isset ( $this -> meta -> username )) {
self :: setUserName ();
}
if ( ! isset ( $this -> meta -> fidelity )) {
$this -> meta -> fidelity = '' ;
}
if ( ! isset ( $this -> meta -> document_name )) {
$this -> meta -> document_name = '' ;
}
if ( ! isset ( $this -> meta -> sides )) {
$this -> meta -> sides = '' ;
}
if ( ! isset ( $this -> meta -> page_ranges )) {
$this -> meta -> page_ranges = '' ;
}
$jobattributes = '' ;
$operationattributes = '' ;
$printerattributes = '' ;
$this -> _buildValues ( $operationattributes , $jobattributes , $printerattributes );
self :: _setOperationId ();
if ( ! isset ( $this -> error_generation -> request_body_malformed ))
{
$this -> error_generation -> request_body_malformed = " " ;
}
$this -> stringjob = chr ( 0x01 ) . chr ( 0x01 ) // 1.1 | version-number
. chr ( 0x00 ) . chr ( 0x02 ) // Print-Job | operation-id
. $this -> meta -> operation_id // request-id
. chr ( 0x01 ) // start operation-attributes | operation-attributes-tag
. $this -> meta -> charset
. $this -> meta -> language
. $this -> meta -> printer_uri
. $this -> meta -> username
. $this -> meta -> jobname
. $this -> meta -> fidelity
. $this -> meta -> document_name
. $this -> meta -> mime_media_type
. $operationattributes ;
2015-05-30 16:14:54 +02:00
if ( $this -> meta -> copies || $this -> meta -> sides || $this -> meta -> page_ranges || ! empty ( $jobattributes ))
2014-12-28 11:29:53 +01:00
{
$this -> stringjob .=
chr ( 0x02 ) // start job-attributes | job-attributes-tag
. $this -> meta -> copies
. $this -> meta -> sides
. $this -> meta -> page_ranges
. $jobattributes ;
}
$this -> stringjob .= chr ( 0x03 ); // end-of-attributes | end-of-attributes-tag
self :: _putDebug (
sprintf ( _ ( " String sent to the server is: %s " ),
$this -> stringjob )
2013-03-08 11:17:46 +01:00
);
2014-12-28 11:29:53 +01:00
return TRUE ;
}
2015-05-30 16:14:54 +02:00
protected function _buildValues ( & $operationattributes , & $jobattributes , & $printerattributes )
2014-12-28 11:29:53 +01:00
{
$operationattributes = '' ;
2015-05-30 16:14:54 +02:00
foreach ( $this -> operation_tags as $key => $values )
2014-12-28 11:29:53 +01:00
{
$item = 0 ;
if ( array_key_exists ( 'value' , $values ))
{
2015-05-30 16:14:54 +02:00
foreach ( $values [ 'value' ] as $item_value )
2014-12-28 11:29:53 +01:00
{
if ( $item == 0 )
{
$operationattributes .=
2015-05-30 16:14:54 +02:00
$values [ 'systag' ]
. self :: _giveMeStringLength ( $key )
. $key
. self :: _giveMeStringLength ( $item_value )
2014-12-28 11:29:53 +01:00
. $item_value ;
}
else
{
2015-05-30 16:14:54 +02:00
$operationattributes .=
$values [ 'systag' ]
. self :: _giveMeStringLength ( '' )
. self :: _giveMeStringLength ( $item_value )
2014-12-28 11:29:53 +01:00
. $item_value ;
}
$item ++ ;
}
}
}
$jobattributes = '' ;
2015-05-30 16:14:54 +02:00
foreach ( $this -> job_tags as $key => $values )
2014-12-28 11:29:53 +01:00
{
$item = 0 ;
2015-05-30 16:14:54 +02:00
if ( array_key_exists ( 'value' , $values ))
2014-12-28 11:29:53 +01:00
{
2015-05-30 16:14:54 +02:00
foreach ( $values [ 'value' ] as $item_value )
2014-12-28 11:29:53 +01:00
{
if ( $item == 0 )
2015-05-30 16:14:54 +02:00
{
2014-12-28 11:29:53 +01:00
$jobattributes .=
2015-05-30 16:14:54 +02:00
$values [ 'systag' ]
2014-12-28 11:29:53 +01:00
. self :: _giveMeStringLength ( $key )
. $key
. self :: _giveMeStringLength ( $item_value )
. $item_value ;
}
else
{
$jobattributes .=
$values [ 'systag' ]
. self :: _giveMeStringLength ( '' )
. self :: _giveMeStringLength ( $item_value )
. $item_value ;
}
$item ++ ;
}
}
}
$printerattributes = '' ;
2015-05-30 16:14:54 +02:00
foreach ( $this -> printer_tags as $key => $values )
2014-12-28 11:29:53 +01:00
{
$item = 0 ;
if ( array_key_exists ( 'value' , $values ))
{
2015-05-30 16:14:54 +02:00
foreach ( $values [ 'value' ] as $item_value )
2014-12-28 11:29:53 +01:00
{
if ( $item == 0 )
{
$printerattributes .=
$values [ 'systag' ]
. self :: _giveMeStringLength ( $key )
. $key
. self :: _giveMeStringLength ( $item_value )
. $item_value ;
}
else
{
$printerattributes .=
$values [ 'systag' ]
. self :: _giveMeStringLength ( '' )
. self :: _giveMeStringLength ( $item_value )
. $item_value ;
}
$item ++ ;
}
}
}
reset ( $this -> job_tags );
reset ( $this -> operation_tags );
reset ( $this -> printer_tags );
return true ;
}
2015-05-30 16:14:54 +02:00
protected function _giveMeStringLength ( $string )
2014-12-28 11:29:53 +01:00
{
$length = strlen ( $string );
if ( $length > (( 0xFF << 8 ) + 0xFF ) )
{
$errmsg = sprintf (
_ ( 'max string length for an ipp meta-information = %d, while here %d' ),
(( 0xFF << 8 ) + 0xFF ), $length );
if ( $this -> with_exceptions )
{
throw new ippException ( $errmsg );
}
else
{
trigger_error ( $errmsg , E_USER_ERROR );
}
}
$int1 = $length & 0xFF ;
$length -= $int1 ;
$length = $length >> 8 ;
$int2 = $length & 0xFF ;
return chr ( $int2 ) . chr ( $int1 );
}
2015-05-30 16:14:54 +02:00
protected function _enumBuild ( $tag , $value )
2014-12-28 11:29:53 +01:00
{
2015-05-30 16:14:54 +02:00
switch ( $tag )
2014-12-28 11:29:53 +01:00
{
case " orientation-requested " :
2015-05-30 16:14:54 +02:00
switch ( $value )
2014-12-28 11:29:53 +01:00
{
case 'portrait' :
$value = chr ( 3 );
break ;
case 'landscape' :
$value = chr ( 4 );
break ;
case 'reverse-landscape' :
$value = chr ( 5 );
break ;
case 'reverse-portrait' :
$value = chr ( 6 );
break ;
}
break ;
case " print-quality " :
2015-05-30 16:14:54 +02:00
switch ( $value )
2014-12-28 11:29:53 +01:00
{
case 'draft' :
$value = chr ( 3 );
break ;
case 'normal' :
$value = chr ( 4 );
break ;
case 'high' :
$value = chr ( 5 );
break ;
}
break ;
case " finishing " :
2015-05-30 16:14:54 +02:00
switch ( $value )
2014-12-28 11:29:53 +01:00
{
case 'none' :
$value = chr ( 3 );
break ;
case 'staple' :
$value = chr ( 4 );
break ;
case 'punch' :
$value = chr ( 5 );
break ;
case 'cover' :
$value = chr ( 6 );
break ;
case 'bind' :
$value = chr ( 7 );
break ;
case 'saddle-stitch' :
$value = chr ( 8 );
break ;
case 'edge-stitch' :
$value = chr ( 9 );
break ;
case 'staple-top-left' :
$value = chr ( 20 );
break ;
case 'staple-bottom-left' :
$value = chr ( 21 );
break ;
case 'staple-top-right' :
$value = chr ( 22 );
break ;
case 'staple-bottom-right' :
$value = chr ( 23 );
break ;
case 'edge-stitch-left' :
$value = chr ( 24 );
break ;
case 'edge-stitch-top' :
$value = chr ( 25 );
break ;
case 'edge-stitch-right' :
$value = chr ( 26 );
break ;
case 'edge-stitch-bottom' :
$value = chr ( 27 );
break ;
case 'staple-dual-left' :
$value = chr ( 28 );
break ;
case 'staple-dual-top' :
$value = chr ( 29 );
break ;
case 'staple-dual-right' :
$value = chr ( 30 );
break ;
case 'staple-dual-bottom' :
$value = chr ( 31 );
break ;
}
break ;
}
$prepend = '' ;
while (( strlen ( $value ) + strlen ( $prepend )) < 4 )
{
$prepend .= chr ( 0 );
}
return $prepend . $value ;
}
2015-05-30 16:14:54 +02:00
protected function _integerBuild ( $value )
2014-12-28 11:29:53 +01:00
{
2015-05-30 16:14:54 +02:00
if ( $value >= 2147483647 || $value < - 2147483648 )
2014-12-28 11:29:53 +01:00
{
trigger_error (
_ ( " Values must be between -2147483648 and 2147483647: assuming '0' " ) , E_USER_WARNING );
return chr ( 0x00 ) . chr ( 0x00 ) . chr ( 0x00 ) . chr ( 0x00 );
}
$initial_value = $value ;
$int1 = $value & 0xFF ;
$value -= $int1 ;
$value = $value >> 8 ;
$int2 = $value & 0xFF ;
$value -= $int2 ;
$value = $value >> 8 ;
$int3 = $value & 0xFF ;
$value -= $int3 ;
$value = $value >> 8 ;
$int4 = $value & 0xFF ; //64bits
if ( $initial_value < 0 ) {
$int4 = chr ( $int4 ) | chr ( 0x80 );
}
else {
$int4 = chr ( $int4 );
}
$value = $int4 . chr ( $int3 ) . chr ( $int2 ) . chr ( $int1 );
return $value ;
}
2015-05-30 16:14:54 +02:00
protected function _rangeOfIntegerBuild ( $integers )
2014-12-28 11:29:53 +01:00
{
#$integers = split(":", $integers);
$integers = preg_split ( " #:# " , $integers );
for ( $i = 0 ; $i < 2 ; $i ++ ) {
$outvalue [ $i ] = self :: _integerBuild ( $integers [ $i ]);
}
return $outvalue [ 0 ] . $outvalue [ 1 ];
}
2015-05-30 16:14:54 +02:00
protected function _setJobAttribute ( $attribute , $value )
2014-12-28 11:29:53 +01:00
{
//used by setAttribute
$tag_type = $this -> job_tags [ $attribute ][ 'tag' ];
2015-05-30 16:14:54 +02:00
switch ( $tag_type )
2014-12-28 11:29:53 +01:00
{
case 'integer' :
$this -> job_tags [ $attribute ][ 'value' ][] = self :: _integerBuild ( $value );
break ;
case 'boolean' :
case 'nameWithoutLanguage' :
case 'nameWithLanguage' :
case 'textWithoutLanguage' :
case 'textWithLanguage' :
case 'keyword' :
case 'naturalLanguage' :
$this -> job_tags [ $attribute ][ 'value' ][] = $value ;
break ;
case 'enum' :
$value = $this -> _enumBuild ( $attribute , $value ); // may be overwritten by children
$this -> job_tags [ $attribute ][ 'value' ][] = $value ;
break ;
case 'rangeOfInteger' :
// $value have to be: INT1:INT2 , eg 100:1000
$this -> job_tags [ $attribute ][ 'value' ][] = self :: _rangeOfIntegerBuild ( $value );
break ;
case 'resolution' :
if ( preg_match ( " #dpi# " , $value )) {
$unit = chr ( 0x3 );
}
if ( preg_match ( " #dpc# " , $value )) {
$unit = chr ( 0x4 );
}
$search = array (
" #(dpi|dpc)# " ,
'#(x|-)#'
);
$replace = array (
" " ,
" : "
);
$value = self :: _rangeOfIntegerBuild ( preg_replace ( $search , $replace , $value )) . $unit ;
$this -> job_tags [ $attribute ][ 'value' ][] = $value ;
break ;
default :
trigger_error ( sprintf ( _ ( 'SetAttribute: Tag "%s": cannot set attribute' ) , $attribute ) , E_USER_NOTICE );
self :: _putDebug ( sprintf ( _ ( 'SetAttribute: Tag "%s": cannot set attribute' ) , $attribute ) , 2 );
self :: _errorLog ( sprintf ( _ ( 'SetAttribute: Tag "%s": cannot set attribute' ) , $attribute ) , 2 );
return FALSE ;
break ;
}
$this -> job_tags [ $attribute ][ 'systag' ] = $this -> tags_types [ $tag_type ][ 'tag' ];
}
2015-05-30 16:14:54 +02:00
protected function _setOperationAttribute ( $attribute , $value )
2014-12-28 11:29:53 +01:00
{
//used by setAttribute
$tag_type = $this -> operation_tags [ $attribute ][ 'tag' ];
2015-05-30 16:14:54 +02:00
switch ( $tag_type )
2014-12-28 11:29:53 +01:00
{
case 'integer' :
$this -> operation_tags [ $attribute ][ 'value' ][] = self :: _integerBuild ( $value );
break ;
case 'keyword' :
case 'naturalLanguage' :
$this -> operation_tags [ $attribute ][ 'value' ][] = $value ;
break ;
default :
trigger_error ( sprintf ( _ ( 'SetAttribute: Tag "%s": cannot set attribute' ) , $attribute ) , E_USER_NOTICE );
self :: _putDebug ( sprintf ( _ ( 'SetAttribute: Tag "%s": cannot set attribute' ) , $attribute ) , 2 );
self :: _errorLog ( sprintf ( _ ( 'SetAttribute: Tag "%s": cannot set attribute' ) , $attribute ) , 2 );
return FALSE ;
break ;
}
$this -> operation_tags [ $attribute ][ 'systag' ] = $this -> tags_types [ $tag_type ][ 'tag' ];
}
2015-05-30 16:14:54 +02:00
protected function _setPrinterAttribute ( $attribute , $value )
2014-12-28 11:29:53 +01:00
{
//used by setAttribute
$tag_type = $this -> printer_tags [ $attribute ][ 'tag' ];
2015-05-30 16:14:54 +02:00
switch ( $tag_type )
2014-12-28 11:29:53 +01:00
{
case 'integer' :
$this -> printer_tags [ $attribute ][ 'value' ][] = self :: _integerBuild ( $value );
break ;
case 'keyword' :
case 'naturalLanguage' :
$this -> printer_tags [ $attribute ][ 'value' ][] = $value ;
break ;
default :
trigger_error ( sprintf ( _ ( 'SetAttribute: Tag "%s": cannot set attribute' ) , $attribute ) , E_USER_NOTICE );
self :: _putDebug ( sprintf ( _ ( 'SetAttribute: Tag "%s": cannot set attribute' ) , $attribute ) , 2 );
self :: _errorLog ( sprintf ( _ ( 'SetAttribute: Tag "%s": cannot set attribute' ) , $attribute ) , 2 );
return FALSE ;
break ;
}
$this -> printer_tags [ $attribute ][ 'systag' ] = $this -> tags_types [ $tag_type ][ 'tag' ];
}
//
// DEBUGGING
//
2015-05-30 16:14:54 +02:00
protected function _putDebug ( $string , $level = 1 )
2014-12-28 11:29:53 +01:00
{
if ( $level === false ) {
return ;
}
if ( $level < $this -> debug_level ) {
return ;
}
$this -> debug [ $this -> debug_count ] = substr ( $string , 0 , 1024 );
$this -> debug_count ++ ;
//$this->debug .= substr($string,0,1024);
}
//
// LOGGING
//
2015-05-30 16:14:54 +02:00
protected function _errorLog ( $string_to_log , $level )
2014-12-28 11:29:53 +01:00
{
if ( $level > $this -> log_level ) {
return ;
}
$string = sprintf ( '%s : %s:%s user %s : %s' , basename ( $_SERVER [ 'PHP_SELF' ]) , $this -> host , $this -> port , $this -> requesting_user , $string_to_log );
2015-05-30 16:14:54 +02:00
if ( $this -> log_type == 0 )
2014-12-28 11:29:53 +01:00
{
error_log ( $string );
return ;
}
$string = sprintf ( " %s %s Host %s:%s user %s : %s \n " , date ( 'M d H:i:s' ) , basename ( $_SERVER [ 'PHP_SELF' ]) , $this -> host , $this -> port , $this -> requesting_user , $string_to_log );
error_log ( $string , $this -> log_type , $this -> log_destination );
return ;
}
}