PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/root/usr/share/nethesis/NethServer/Tool/phpprintipp/CupsPrintIPP.php

https://github.com/nethesis/nethserver-cups
PHP | 671 lines | 462 code | 120 blank | 89 comment | 105 complexity | c5e931c42d5d38c854e728ade7d57d0e MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
  3. /* @(#) $Header: /sources/phpprintipp/phpprintipp/php_classes/CupsPrintIPP.php,v 1.1 2008/06/21 00:30:56 harding Exp $
  4. *
  5. * Class PrintIPP - Send extended IPP requests.
  6. *
  7. * Copyright (C) 2005-2006 Thomas HARDING
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Library General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Library General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Library General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. *
  23. * mailto:thomas.harding@laposte.net
  24. * Thomas Harding, 56 rue de la bourie rouge, 45 000 ORLEANS -- FRANCE
  25. *
  26. */
  27. /*
  28. This class is intended to implement Internet Printing Protocol on client side.
  29. References needed to debug / add functionnalities:
  30. - RFC 2910
  31. - RFC 2911
  32. - RFC 3382
  33. - ...
  34. - CUPS-IPP-1.1
  35. */
  36. require_once("ExtendedPrintIPP.php");
  37. class CupsPrintIPP extends ExtendedPrintIPP {
  38. // {{{ variables declaration
  39. public $printers_attributes;
  40. public $defaults_attributes;
  41. // }}}
  42. // {{{ constructor
  43. public function __construct() {
  44. parent::__construct();
  45. self::_initTags();
  46. }
  47. // }}}
  48. //
  49. // OPERATIONS
  50. //
  51. // {{{ cupsGetDefaults ($attributes="all")
  52. public function cupsGetDefaults($attributes=array("all")) {
  53. //The CUPS-Get-Default operation returns the default printer URI and attributes
  54. $this->jobs = array_merge($this->jobs,array(""));
  55. $this->jobs_uri = array_merge($this->jobs_uri,array(""));
  56. $this->parsed = array();
  57. unset($this->printer_attributes);
  58. if (!isset($this->setup->charset))
  59. self::setCharset('us-ascii');
  60. if (!isset($this->setup->language))
  61. self::setLanguage('en');
  62. self::_setOperationId();
  63. for($i = 0 ; $i < count($attributes) ; $i++)
  64. if ($i == 0)
  65. $this->meta->attributes = chr(0x44) // Keyword
  66. . self::_giveMeStringLength('requested-attributes')
  67. . 'requested-attributes'
  68. . self::_giveMeStringLength($attributes[0])
  69. . $attributes[0];
  70. else
  71. $this->meta->attributes .= chr(0x44) // Keyword
  72. . chr(0x0).chr(0x0) // zero-length name
  73. . self::_giveMeStringLength($attributes[$i])
  74. . $attributes[$i];
  75. $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
  76. . chr(0x40). chr(0x01) // operation: cups vendor extension: get defaults
  77. . $this->meta->operation_id // request-id
  78. . chr(0x01) // start operation-attributes | operation-attributes-tag
  79. . $this->meta->charset
  80. . $this->meta->language
  81. . $this->meta->attributes
  82. . chr(0x03); // end operations attribute
  83. $this->output = $this->stringjob;
  84. self::_putDebug("Request: ".$this->output);
  85. $post_values = array( "Content-Type" => "application/ipp",
  86. "Data" => $this->output);
  87. if (self::_sendHttp ($post_values,'/')) {
  88. if(self::_parseServerOutput())
  89. self::_parsePrinterAttributes();
  90. }
  91. $this->attributes = &$this->printer_attributes;
  92. if (isset($this->printer_attributes->printer_type)) {
  93. $printer_type = $this->printer_attributes->printer_type->_value0;
  94. $table = self::_interpretPrinterType($printer_type);
  95. for($i = 0 ; $i < count($table) ; $i++ ) {
  96. $index = '_value'.$i;
  97. $this->printer_attributes->printer_type->$index = $table[$i];
  98. }
  99. }
  100. if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
  101. $this->status = array_merge($this->status,array($this->serveroutput->status));
  102. if ($this->serveroutput->status == "successfull-ok")
  103. self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
  104. else
  105. self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
  106. return $this->serveroutput->status;
  107. } else {
  108. $this->status = array_merge($this->status,array("OPERATION FAILED"));
  109. self::_errorLog("getting defaults : OPERATION FAILED",1);
  110. }
  111. return false;
  112. }
  113. // }}}
  114. // {{{ cupsAcceptJobs ($printer_uri)
  115. public function cupsAcceptJobs($printer_uri) {
  116. //The CUPS-Get-Default operation returns the default printer URI and attributes
  117. $this->jobs = array_merge($this->jobs,array(""));
  118. $this->jobs_uri = array_merge($this->jobs_uri,array(""));
  119. $this->parsed = array();
  120. unset($this->printer_attributes);
  121. if (!isset($this->setup->charset))
  122. self::setCharset('us-ascii');
  123. if (!isset($this->setup->language))
  124. self::setLanguage('en');
  125. self::_setOperationId();
  126. $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
  127. . chr(0x40). chr(0x08) // operation: cups vendor extension: Accept-Jobs
  128. . $this->meta->operation_id // request-id
  129. . chr(0x01) // start operation-attributes | operation-attributes-tag
  130. . $this->meta->charset
  131. . $this->meta->language
  132. . chr(0x45) // uri
  133. . self::_giveMeStringLength('printer-uri')
  134. . 'printer-uri'
  135. . self::_giveMeStringLength($printer_uri)
  136. . $printer_uri
  137. . chr(0x03); // end operations attribute
  138. $this->output = $this->stringjob;
  139. self::_putDebug("Request: ".$this->output);
  140. $post_values = array( "Content-Type" => "application/ipp",
  141. "Data" => $this->output);
  142. if (self::_sendHttp ($post_values,'/admin/')) {
  143. if(self::_parseServerOutput())
  144. self::_parseAttributes();
  145. }
  146. if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
  147. $this->status = array_merge($this->status,array($this->serveroutput->status));
  148. if ($this->serveroutput->status == "successfull-ok")
  149. self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
  150. else
  151. self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
  152. return $this->serveroutput->status;
  153. } else {
  154. $this->status = array_merge($this->status,array("OPERATION FAILED"));
  155. self::_errorLog("getting defaults : OPERATION FAILED",1);
  156. }
  157. return false;
  158. }
  159. // }}}
  160. // {{{ cupsRejectJobs ($printer_uri,$printer_state_message=false)
  161. public function cupsRejectJobs($printer_uri,$printer_state_message) {
  162. //The CUPS-Get-Default operation returns the default printer URI and attributes
  163. $this->jobs = array_merge($this->jobs,array(""));
  164. $this->jobs_uri = array_merge($this->jobs_uri,array(""));
  165. $this->parsed = array();
  166. unset($this->attributes);
  167. if (!isset($this->setup->charset))
  168. self::setCharset('us-ascii');
  169. if (!isset($this->setup->language))
  170. self::setLanguage('en');
  171. self::_setOperationId();
  172. $message = "";
  173. if ($printer_state_message)
  174. $message = chr(0x04) // start printer-attributes
  175. . chr(0x41) // textWithoutLanguage
  176. . self::_giveMeStringLength("printer-state-message")
  177. . "printer-state-message"
  178. . self::_giveMeStringLength($printer_state_message)
  179. . $printer_state_message;
  180. $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
  181. . chr(0x40). chr(0x09) // operation: cups vendor extension: Reject-Jobs
  182. . $this->meta->operation_id // request-id
  183. . chr(0x01) // start operation-attributes | operation-attributes-tag
  184. . $this->meta->charset
  185. . $this->meta->language
  186. . chr(0x45) // uri
  187. . self::_giveMeStringLength('printer-uri')
  188. . 'printer-uri'
  189. . self::_giveMeStringLength($printer_uri)
  190. . $printer_uri
  191. . $message
  192. . chr(0x03); // end operations attribute
  193. $this->output = $this->stringjob;
  194. self::_putDebug("Request: ".$this->output);
  195. $post_values = array( "Content-Type" => "application/ipp",
  196. "Data" => $this->output);
  197. if (self::_sendHttp ($post_values,'/admin/')) {
  198. if(self::_parseServerOutput())
  199. self::_parseAttributes();
  200. }
  201. if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
  202. $this->status = array_merge($this->status,array($this->serveroutput->status));
  203. if ($this->serveroutput->status == "successfull-ok")
  204. self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
  205. else
  206. self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
  207. return $this->serveroutput->status;
  208. } else {
  209. $this->status = array_merge($this->status,array("OPERATION FAILED"));
  210. self::_errorLog("getting defaults : OPERATION FAILED",1);
  211. }
  212. return false;
  213. }
  214. // }}}
  215. // {{{ getPrinters()
  216. public function getPrinters($printer_location=false,$printer_info=false,$attributes=array()) {
  217. if (count($attributes) == 0)
  218. true;
  219. $attributes=array('printer-uri-supported','printer-location','printer-info','printer-type','color-supported');
  220. $this->jobs = array_merge($this->jobs,array(""));
  221. $this->jobs_uri = array_merge($this->jobs_uri,array(""));
  222. unset ($this->printers_attributes);
  223. if (!isset($this->setup->charset))
  224. self::setCharset('us-ascii');
  225. if (!isset($this->setup->language))
  226. self::setLanguage('en-us');
  227. self::_setOperationId();
  228. $this->meta->attributes='';
  229. if ($printer_location)
  230. $this->meta->attributes .= chr(0x41) // textWithoutLanguage
  231. . self::_giveMeStringLength('printer-location')
  232. . 'printer-location'
  233. . self::_giveMeStringLength($printer_location)
  234. . $printer_location;
  235. if ($printer_info)
  236. $this->meta->attributes .= chr(0x41) // textWithoutLanguage
  237. . self::_giveMeStringLength('printer-info')
  238. . 'printer-info'
  239. . self::_giveMeStringLength($printer_info)
  240. . $printer_info;
  241. for($i = 0 ; $i < count($attributes) ; $i++)
  242. if ($i == 0)
  243. $this->meta->attributes .= chr(0x44) // Keyword
  244. . self::_giveMeStringLength('requested-attributes')
  245. . 'requested-attributes'
  246. . self::_giveMeStringLength($attributes[0])
  247. . $attributes[0];
  248. else
  249. $this->meta->attributes .= chr(0x44) // Keyword
  250. . chr(0x0).chr(0x0) // zero-length name
  251. . self::_giveMeStringLength($attributes[$i])
  252. . $attributes[$i];
  253. $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
  254. . chr(0x40). chr(0x02) // operation: cups vendor extension: get printers
  255. . $this->meta->operation_id // request-id
  256. . chr(0x01) // start operation-attributes | operation-attributes-tag
  257. . $this->meta->charset
  258. . $this->meta->language
  259. . $this->meta->attributes
  260. . chr(0x03); // end operations attribute
  261. $this->output = $this->stringjob;
  262. $post_values = array( "Content-Type" => "application/ipp",
  263. "Data" => $this->output);
  264. if (self::_sendHttp ($post_values,'/')) {
  265. if(self::_parseServerOutput())
  266. $this->_getAvailablePrinters();
  267. }
  268. if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
  269. $this->status = array_merge($this->status,array($this->serveroutput->status));
  270. if ($this->serveroutput->status == "successfull-ok")
  271. self::_errorLog("getting printers: ".$this->serveroutput->status,3);
  272. else
  273. self::_errorLog("getting printers: ".$this->serveroutput->status,1);
  274. return $this->serveroutput->status;
  275. } else {
  276. $this->status = array_merge($this->status,array("OPERATION FAILED"));
  277. self::_errorLog("getting printers : OPERATION FAILED",1);
  278. }
  279. return false;
  280. }
  281. // }}}
  282. // {{{ cupsGetPrinters ()
  283. public function cupsGetPrinters () {
  284. // alias for getPrinters();
  285. self::getPrinters();
  286. }
  287. // }}}
  288. // {{{ getPrinterAttributes()
  289. public function getPrinterAttributes() {
  290. // complete informations from parent with Cups-specific stuff
  291. if(!$result = parent::getPrinterAttributes())
  292. return FALSE;
  293. if(!isset($this->printer_attributes))
  294. return FALSE;
  295. if (isset ($this->printer_attributes->printer_type)) {
  296. $printer_type = $this->printer_attributes->printer_type->_value0;
  297. $table = self::_interpretPrinterType($printer_type);
  298. for($i = 0 ; $i < count($table) ; $i++ ) {
  299. $index = '_value'.$i;
  300. $this->printer_attributes->printer_type->$index = $table[$i];
  301. }
  302. }
  303. return $result;
  304. }
  305. // }}}
  306. //
  307. // SETUP
  308. //
  309. // {{{ _initTags ()
  310. protected function _initTags () {
  311. // override parent with specific cups attributes
  312. $operation_tags = array ();
  313. $this->operation_tags = array_merge ($this->operation_tags, $operation_tags);
  314. $job_tags = array ( "job-billing" => array("tag" => "textWithoutLanguage"),
  315. "blackplot" => array("tag" => "boolean"),
  316. "brightness" => array("tag" => "integer"),
  317. "columns" => array("tag" => "integer"),
  318. "cpi" => array("tag" => "enum"),
  319. "fitplot" => array("tag" => "boolean"),
  320. "gamma" => array("tag" => "integer"),
  321. "hue" => array("tag" => "integer"),
  322. "lpi" => array("tag" => "enum"),
  323. "mirror" => array("tag","boolean"),
  324. "natural-scaling" => array("tag" => "integer"),
  325. "number-up-layout" => array("tag" => "keyword"),
  326. "page-border" => array("tag" => "keyword"),
  327. "page-bottom" => array("tag" => "integer"),
  328. "page-label" => array("tag" => "textWithoutLanguage"),
  329. "page-left" => array("tag" => "integer"),
  330. "page-right" => array("tag" => "integer"),
  331. "page-set" => array("tag" => "keyword"),
  332. "page-top" => array("tag" => "integer"),
  333. "penwidth" => array("tag" => "integer"),
  334. "position" => array("tag" => "keyword"),
  335. "ppi" => array("tag" => "integer"),
  336. "prettyprint" => array("tag","boolean"),
  337. "saturation" => array("tag" => "integer"),
  338. "scaling" => array("tag" => "integer"),
  339. "wrap" => array("tag","boolean"),
  340. );
  341. $this->job_tags = array_merge ($this->job_tags, $job_tags);
  342. }
  343. // }}}
  344. //
  345. // REQUEST BUILDING
  346. //
  347. // {{{ _enumBuild ($tag,$value)
  348. protected function _enumBuild ($tag,$value) {
  349. $value_built = parent::_enumBuild($tag,$value);
  350. switch ($tag) {
  351. case "cpi":
  352. switch ($value) {
  353. case '10':
  354. $value_built = chr(10);
  355. break;
  356. case '12':
  357. $value_built = chr(12);
  358. break;
  359. case '17':
  360. $value_built = chr(17);
  361. break;
  362. default:
  363. $value_built = chr(10);
  364. }
  365. break;
  366. case "lpi":
  367. switch ($value) {
  368. case '6':
  369. $value_built = chr(6);
  370. break;
  371. case '8':
  372. $value_built = chr(8);
  373. break;
  374. default:
  375. $value_built = chr(6);
  376. }
  377. break;
  378. }
  379. $prepend = '';
  380. while ((strlen($value_built) + strlen($prepend)) < 4)
  381. $prepend .= chr(0);
  382. return $prepend.$value_built;
  383. }
  384. // }}}
  385. //
  386. // RESPONSE PARSING
  387. //
  388. // {{{ _getAvailablePrinters ()
  389. private function _getAvailablePrinters () {
  390. $this->available_printers = array();
  391. $k = 0;
  392. $this->printers_attributes = new stdClass();
  393. for ($i = 0 ; (array_key_exists($i,$this->serveroutput->response)) ; $i ++)
  394. if (($this->serveroutput->response[$i]['attributes']) == "printer-attributes") {
  395. $phpname = "_printer".$k;
  396. $this->printers_attributes->$phpname = new stdClass();
  397. for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++) {
  398. $value = $this->serveroutput->response[$i][$j]['value'];
  399. $name = str_replace("-","_",$this->serveroutput->response[$i][$j]['name']);
  400. switch ($name) {
  401. case "printer_uri_supported":
  402. $this->available_printers = array_merge($this->available_printers,array($value));
  403. break;
  404. case "printer_type":
  405. $table = self::_interpretPrinterType($value);
  406. $this->printers_attributes->$phpname->$name = new stdClass();
  407. for($l = 0 ; $l < count($table) ; $l++ ) {
  408. $index = '_value'.$l;
  409. $this->printers_attributes->$phpname->$name->$index = $table[$l];
  410. }
  411. break;
  412. case '':
  413. break;
  414. default:
  415. $this->printers_attributes->$phpname->$name = $value;
  416. break;
  417. }
  418. }
  419. $k ++;
  420. }
  421. }
  422. // }}}
  423. // {{{ _getEnumVendorExtensions
  424. protected function _getEnumVendorExtensions ($value_parsed) {
  425. switch ($value_parsed) {
  426. case 0x4002:
  427. $value = 'Get-Availables-Printers';
  428. break;
  429. default:
  430. $value = sprintf('Unknown(Cups extension for operations): 0x%x',$value_parsed);
  431. break;
  432. }
  433. if (isset($value))
  434. return ($value);
  435. return sprintf('Unknown: 0x%x',$value_parsed);
  436. }
  437. // }}}
  438. // {{{ _interpretPrinterType($type)
  439. private function _interpretPrinterType($value) {
  440. $value_parsed = 0;
  441. for ($i = strlen($value) ; $i > 0 ; $i --)
  442. $value_parsed += pow(256,($i - 1)) * ord($value[strlen($value) - $i]);
  443. $type[0] = $type[1] = $type[2] = $type[3] = $type[4] = $type[5] = '';
  444. $type[6] = $type[7] = $type[8] = $type[9] = $type[10] = '';
  445. $type[11] = $type[12] = $type[13] = $type[14] = $type[15] = '';
  446. $type[16] = $type[17] = $type[18] = $type[19] = '';
  447. if ($value_parsed %2 == 1) {
  448. $type[0] = 'printer-class';
  449. $value_parsed -= 1;
  450. }
  451. if ($value_parsed %4 == 2 ) {
  452. $type[1] = 'remote-destination';
  453. $value_parsed -= 2;
  454. }
  455. if ($value_parsed %8 == 4 ) {
  456. $type[2] = 'print-black';
  457. $value_parsed -= 4;
  458. }
  459. if ($value_parsed %16 == 8 ) {
  460. $type[3] = 'print-color';
  461. $value_parsed -= 8;
  462. }
  463. if ($value_parsed %32 == 16) {
  464. $type[4] = 'hardware-print-on-both-sides';
  465. $value_parsed -= 16;
  466. }
  467. if ($value_parsed %64 == 32) {
  468. $type[5] = 'hardware-staple-output';
  469. $value_parsed -= 32;
  470. }
  471. if ($value_parsed %128 == 64) {
  472. $type[6] = 'hardware-fast-copies';
  473. $value_parsed -= 64;
  474. }
  475. if ($value_parsed %256 == 128) {
  476. $type[7] = 'hardware-fast-copy-collation';
  477. $value_parsed -= 128;
  478. }
  479. if ($value_parsed %512 == 256) {
  480. $type[8] = 'punch-output';
  481. $value_parsed -= 256;
  482. }
  483. if ($value_parsed %1024 == 512) {
  484. $type[9] = 'cover-output';
  485. $value_parsed -= 512;
  486. }
  487. if ($value_parsed %2048 == 1024) {
  488. $type[10] = 'bind-output';
  489. $value_parsed -= 1024;
  490. }
  491. if ($value_parsed %4096 == 2048) {
  492. $type[11] = 'sort-output';
  493. $value_parsed -= 2048;
  494. }
  495. if ($value_parsed %8192 == 4096) {
  496. $type[12] = 'handle-media-up-to-US-Legal-A4';
  497. $value_parsed -= 4096;
  498. }
  499. if ($value_parsed %16384 == 8192) {
  500. $type[13] = 'handle-media-between-US-Legal-A4-and-ISO_C-A2';
  501. $value_parsed -= 8192;
  502. }
  503. if ($value_parsed %32768 == 16384) {
  504. $type[14] = 'handle-media-larger-than-ISO_C-A2';
  505. $value_parsed -= 16384;
  506. }
  507. if ($value_parsed %65536 == 32768) {
  508. $type[15] = 'handle-user-defined-media-sizes';
  509. $value_parsed -= 32768;
  510. }
  511. if ($value_parsed %131072 == 65536) {
  512. $type[16] = 'implicit-server-generated-class';
  513. $value_parsed -= 65536;
  514. }
  515. if ($value_parsed %262144 == 131072) {
  516. $type[17] = 'network-default-printer';
  517. $value_parsed -= 131072;
  518. }
  519. if ($value_parsed %524288 == 262144) {
  520. $type[18] = 'fax-device';
  521. $value_parsed -= 262144;
  522. }
  523. return $type;
  524. }
  525. // }}}
  526. // {{{ _interpretEnum()
  527. protected function _interpretEnum($attribute_name,$value) {
  528. $value_parsed = self::_interpretInteger($value);
  529. switch ($attribute_name) {
  530. case 'cpi':
  531. case 'lpi':
  532. $value = $value_parsed;
  533. break;
  534. default:
  535. $value = parent::_interpretEnum($attribute_name,$value);
  536. break;
  537. }
  538. return $value;
  539. }
  540. // }}}
  541. };
  542. /*
  543. * Local variables:
  544. * mode: php
  545. * tab-width: 4
  546. * c-basic-offset: 4
  547. * End:
  548. */
  549. ?>