Test Failed
Push — main ( c8394f...8477f1 )
by Rafael
66:21
created

PrintIPP   F

Complexity

Total Complexity 337

Size/Duplication

Total Lines 2014
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 1298
dl 0
loc 2014
rs 0.8
c 0
b 0
f 0
wmc 337

How to fix   Complexity   

Complex Class

Complex classes like PrintIPP often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PrintIPP, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
 /* @(#) $Header: /sources/phpprintipp/phpprintipp/php_classes/PrintIPP.php,v 1.3 2010/09/06 22:41:41 harding Exp $
4
 *
5
 * Class PrintIPP - Send IPP requests, Get and parses IPP Responses.
6
 *
7
 *   Copyright (C) 2005-2006  Thomas HARDING
8
 *   Parts Copyright (C) 2005-2006 Manuel Lemos
9
 *
10
 *   This library is free software; you can redistribute it and/or
11
 *   modify it under the terms of the GNU Library General Public
12
 *   License as published by the Free Software Foundation; either
13
 *   version 2 of the License, or (at your option) any later version.
14
 *
15
 *   This library is distributed in the hope that it will be useful,
16
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 *   Library General Public License for more details.
19
 *
20
 *   You should have received a copy of the GNU Library General Public
21
 *   License along with this library; if not, write to the Free Software
22
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 *
24
 *   mailto:[email protected]
25
 *   Thomas Harding, 56 rue de la bourie rouge, 45 000 ORLEANS -- FRANCE
26
 *   
27
 */
28
    
29
/*
30
31
    This class is intended to implement Internet Printing Protocol on client side.
32
33
    References needed to debug / add functionnalities:
34
        - RFC 2910
35
        - RFC 2911
36
        - RFC 3380
37
        - RFC 3382
38
*/
39
/*
40
    TODO: beta tests on other servers than Cups
41
*/
42
43
require_once("BasicIPP.php");
44
45
class PrintIPP extends BasicIPP
46
{
47
    public function __construct()
48
    {
49
        parent::__construct();
50
    }
51
52
// OPERATIONS
53
    public function printJob()
54
    {
55
        self::_putDebug(sprintf("*************************\nDate: %s\n*************************\n\n", date('Y-m-d H:i:s')));
56
57
        if (!$this->_stringJob())
58
        {
59
            return FALSE;
60
        }
61
62
        if (is_readable($this->data))
63
        {
64
            self::_putDebug(_("Printing a FILE\n"), 3); 
65
66
            $this->output = $this->stringjob;
67
68
            if ($this->setup->datatype == "TEXT")
69
            {
70
                $this->output .= chr(0x16);
71
            }
72
73
            $post_values = array( "Content-Type" => "application/ipp",
74
                                  "Data" => $this->output,
75
                                  "File" => $this->data);
76
77
            if ($this->setup->datatype == "TEXT" && !isset($this->setup->noFormFeed))
78
            {
79
                $post_values = array_merge($post_values, array("Filetype" => "TEXT"));
80
            }
81
        }
82
        else
83
        {
84
            self::_putDebug(_("Printing DATA\n"), 3); 
85
86
            $this->output = $this->stringjob;
87
            $this->output .= $this->datahead;    
88
            $this->output .= $this->data;
89
            $this->output .= $this->datatail;
90
            
91
            $post_values = array( "Content-Type" => "application/ipp",
92
                                  "Data" => $this->output);
93
        }
94
95
        if (self::_sendHttp($post_values, $this->paths['printers']))
96
        {
97
            if(self::_parseServerOutput())
98
            {
99
                $this->_getJobId();
100
                $this->_getJobUri();
101
                $this->_parseJobAttributes();
102
            }
103
            else
104
            {
105
                $this->jobs = array_merge($this->jobs, array(''));
106
                $this->jobs_uri = array_merge($this->jobs_uri, array(''));
107
                }
108
            }
109
110
        if (isset($this->serveroutput) && isset($this->serveroutput->status))
111
        {
112
            $this->status = array_merge($this->status, array($this->serveroutput->status));
113
114
            if ($this->serveroutput->status == "successfull-ok")
115
            {
116
              self::_errorLog(sprintf("printing job %s: ", $this->last_job) . $this->serveroutput->status, 3);
117
            }
118
            else
119
            {
120
                $this->jobs = array_merge($this->jobs, array(""));
121
                $this->jobs_uri = array_merge($this->jobs_uri, array(""));
122
                self::_errorLog(sprintf("printing job: ", $this->last_job) . $this->serveroutput->status, 1);
123
                if ($this->with_exceptions)
124
                {
125
                    throw new ippException(sprintf(
126
                        "job status: %s",
127
                    $this->serveroutput->status));
128
                }
129
            }
130
            return $this->serveroutput->status; 
131
        }
132
133
        $this->status = array_merge($this->status, array("OPERATION FAILED"));
134
        $this->jobs = array_merge($this->jobs, array(""));
135
        $this->jobs_uri = array_merge($this->jobs_uri, array(""));
136
        self::_errorLog("printing job : OPERATION FAILED", 1);
137
138
        return false;
139
    }
140
141
    public function cancelJob($job_uri)
142
    {
143
        $this->jobs = array_merge($this->jobs, array(""));
144
        $this->jobs_uri = array_merge($this->jobs_uri, array(""));
145
146
        self::_putDebug(sprintf("*************************\nDate: %s\n*************************\n\n", date('Y-m-d H:i:s')));
147
148
        if (!$this->_stringCancel($job_uri))
149
        {
150
            return FALSE;
151
        }
152
153
        self::_putDebug(_("Cancelling Job $job_uri\n"), 3); 
154
155
        $this->output = $this->stringjob;
156
157
        $post_values = array( "Content-Type" => "application/ipp",
158
                              "Data" => $this->output);
159
160
        if (self::_sendHttp($post_values, $this->paths['jobs']))
161
        {
162
            self::_parseServerOutput();
163
        }
164
165
        if (isset($this->serveroutput) && isset($this->serveroutput->status))
166
        {
167
            $this->status = array_merge($this->status, array($this->serveroutput->status));
168
169
            if ($this->serveroutput->status == "successfull-ok")
170
            {
171
                self::_errorLog("cancelling job $job_uri: " . $this->serveroutput->status, 3);
172
            }
173
            else
174
            {
175
                self::_errorLog("cancelling job $job_uri: " . $this->serveroutput->status, 1);
176
            }
177
            return $this->serveroutput->status; 
178
        }
179
180
        $this->status = array_merge($this->status, array("OPERATION FAILED"));
181
        self::_errorLog("cancelling job : OPERATION FAILED", 3);
182
183
        return false;
184
    }
185
186
    public function validateJob()
187
    {
188
        $this->jobs = array_merge($this->jobs, array(""));
189
        $this->jobs_uri = array_merge($this->jobs_uri, array(""));
190
191
        $this->serveroutput->response = '';
192
193
        self::_putDebug(sprintf("*************************\nDate: %s\n*************************\n\n", date('Y-m-d H:i:s')));
194
195
        self::_putDebug(_("Validate Job\n"), 2); 
196
197
        if (!isset($this->setup->charset))
198
        {
199
            self::setCharset();
200
        }
201
        if (!isset($this->setup->datatype))
202
        {
203
            self::setBinary();
204
        }
205
206
        if (!isset($this->setup->uri))
207
        {
208
            $this->getPrinters();
209
            unset($this->jobs[count($this->jobs) - 1]);
210
            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
211
            unset($this->status[count($this->status) - 1]);
212
213
            if (array_key_exists(0, $this->available_printers))
214
            {
215
               self::setPrinterURI($this->available_printers[0]);
216
            }
217
            else
218
            {
219
                trigger_error(_("_stringJob: Printer URI is not set: die"), E_USER_WARNING);
220
                self::_putDebug(_("_stringJob: Printer URI is not set: die\n"), 3);
221
                self::_errorLog(" Printer URI is not set, die", 2);
222
                return FALSE;
223
                }
224
            }
225
226
        if (!isset($this->meta->copies))
227
        {
228
            self::setCopies(1);
229
        }
230
231
        if (!isset($this->setup->copies))
232
        {
233
            self::setCopies(1);
234
        }
235
236
        if (!isset($this->setup->language))
237
        {
238
            self::setLanguage('en_us');
239
        }
240
241
        if (!isset($this->setup->mime_media_type))
242
        {
243
            self::setMimeMediaType();
244
        }
245
246
        if ($this->setup->datatype != "TEXT")
247
        {
248
            unset($this->setup->mime_media_type);
249
        }
250
251
        if (!isset($this->setup->jobname))
252
        {
253
            if (is_readable($this->data))
254
            {
255
                self::setJobName(basename($this->data), true);
256
            }
257
            else
258
            {
259
                self::setJobName();
260
            }
261
        }
262
        unset($this->setup->jobname);
263
264
        if (!isset($this->meta->username))
265
        {
266
            self::setUserName();
267
        }
268
269
        if (!isset($this->meta->fidelity))
270
        {
271
            $this->meta->fidelity = '';
272
        }
273
274
        if (!isset($this->meta->document_name))
275
        {
276
            $this->meta->document_name = '';
277
        }
278
279
        if (!isset($this->meta->sides))
280
        {
281
            $this->meta->sides = '';
282
        }
283
284
        if (!isset($this->meta->page_ranges))
285
        {
286
            $this->meta->page_ranges = '';
287
        }
288
289
        $jobattributes = '';
290
        $operationattributes = '';
291
        $printerattributes = '';
292
        self::_buildValues($operationattributes, $jobattributes, $printerattributes);
293
294
        self::_setOperationId();
295
296
        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
297
                         . chr(0x00) . chr(0x04) // Validate-Job | operation-id
298
                         . $this->meta->operation_id //           request-id
299
                         . chr(0x01) // start operation-attributes | operation-attributes-tag
300
                         . $this->meta->charset
301
                         . $this->meta->language
302
                         . $this->meta->printer_uri
303
                         . $this->meta->username
304
                         . $this->meta->jobname
305
                         . $this->meta->fidelity
306
                         . $this->meta->document_name
307
                         . $this->meta->mime_media_type
308
                         . $operationattributes
309
                         . chr(0x02) // start job-attributes | job-attributes-tag
310
                         . $this->meta->copies
311
                         . $this->meta->sides
312
                         . $this->meta->page_ranges
313
                         . $jobattributes
314
                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
315
316
        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
317
318
        $this->output = $this->stringjob;
319
320
        $post_values = array( "Content-Type" => "application/ipp",
321
                              "Data" => $this->output);
322
323
        if (self::_sendHttp($post_values, $this->paths['printers']))
324
        {
325
            if(self::_parseServerOutput())
326
            {
327
                self::_parseAttributes();
328
            }
329
        }
330
331
        if (isset($this->serveroutput) && isset($this->serveroutput->status))
332
        {
333
            $this->status = array_merge($this->status, array($this->serveroutput->status));
334
335
            if ($this->serveroutput->status == "successfull-ok")
336
            {
337
                self::_errorLog("validate job: " . $this->serveroutput->status, 3);
338
            }
339
            else
340
            {
341
                self::_errorLog("validate job: " . $this->serveroutput->status, 1);
342
            }
343
            return $this->serveroutput->status; 
344
        }
345
346
        $this->status = array_merge($this->status, array("OPERATION FAILED"));
347
        self::_errorLog("validate job : OPERATION FAILED", 3);
348
349
        return false;
350
    }
351
352
    public function getPrinterAttributes()
353
    {
354
        $this->jobs = array_merge($this->jobs, array(""));
355
        $this->jobs_uri = array_merge($this->jobs_uri, array(""));
356
357
        $jobattributes = '';
358
        $operationattributes = '';
359
        self::_buildValues($operationattributes, $jobattributes, $printerattributes);
360
        self::_setOperationId();
361
        $this->parsed = array();
362
        unset($this->printer_attributes);
363
364
        if (!isset($this->setup->uri))
365
        {
366
            $this->getPrinters();
367
            unset($this->jobs[count($this->jobs) - 1]);
368
            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
369
            unset($this->status[count($this->status) - 1]);
370
371
            if (array_key_exists(0, $this->available_printers))
372
            {
373
               self::setPrinterURI($this->available_printers[0]);
374
            }
375
            else
376
            {
377
                trigger_error(_("_stringJob: Printer URI is not set: die"), E_USER_WARNING);
378
                self::_putDebug(_("_stringJob: Printer URI is not set: die\n"), 3);
379
                self::_errorLog(" Printer URI is not set, die", 2);
380
                return FALSE;
381
                }
382
            }
383
384
        if (!isset($this->setup->charset))
385
        {
386
            self::setCharset();
387
        }
388
389
        if (!isset($this->setup->language))
390
        {
391
            self::setLanguage('en_us');
392
        }
393
394
        if (!isset($this->meta->username))
395
        {
396
            self::setUserName();
397
        }
398
399
        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
400
                         . chr(0x00) . chr(0x0b) // Print-URI | operation-id
401
                         . $this->meta->operation_id //           request-id
402
                         . chr(0x01) // start operation-attributes | operation-attributes-tag
403
                         . $this->meta->charset
404
                         . $this->meta->language
405
                         . $this->meta->printer_uri
406
                         . $this->meta->username
407
                         . $printerattributes
408
                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
409
410
        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
411
412
        self::_putDebug(sprintf(_("Getting printer attributes of %s\n"), $this->printer_uri), 2); 
413
414
        $this->output = $this->stringjob;
415
416
        $post_values = array( "Content-Type" => "application/ipp",
417
                              "Data" => $this->output);
418
419
        if (self::_sendHttp($post_values, $this->paths['root']))
420
        {
421
            if (self::_parseServerOutput())
422
            {
423
                self::_parsePrinterAttributes(); 
424
            }
425
        }
426
427
        $this->attributes = &$this->printer_attributes;
428
429
        if (isset($this->serveroutput) && isset($this->serveroutput->status))
430
        {
431
            $this->status = array_merge($this->status, array($this->serveroutput->status));
432
433
            if  ($this->serveroutput->status == "successfull-ok")
434
            {
435
                self::_errorLog(sprintf(
436
                    _("getting printer attributes of %s: %s"), $this->printer_uri,
437
                                                                        $this->serveroutput->status), 3);
438
            }
439
            else 
440
            {
441
                self::_errorLog(sprintf(
442
                    _("getting printer attributes of %s: %s"), $this->printer_uri,
443
                                                                        $this->serveroutput->status), 1);
444
            }
445
446
            return $this->serveroutput->status;
447
        }
448
449
        $this->status = array_merge($this->status, array("OPERATION FAILED"));
450
        self::_errorLog(date("Y-m-d H:i:s : ")
451
            . basename($_SERVER['PHP_SELF'])
452
            . sprintf(
453
                _("getting printer's attributes of %s : OPERATION FAILED"),
454
                $this->printer_uri), 3);
455
456
        return false;
457
    }
458
459
    public function getJobs($my_jobs = true, $limit = 0, $which_jobs = "not-completed", $subset = false)
460
    {
461
        $this->jobs = array_merge($this->jobs, array(""));
462
        $this->jobs_uri = array_merge($this->jobs_uri, array(""));
463
464
        self::_setOperationId();
465
        $this->parsed = array();
466
        unset($this->printer_attributes);
467
468
        if (!isset($this->setup->uri))
469
        {
470
            $this->getPrinters();
471
            unset($this->jobs[count($this->jobs) - 1]);
472
            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
473
            unset($this->status[count($this->status) - 1]);
474
475
            if (array_key_exists(0, $this->available_printers))
476
            {
477
               self::setPrinterURI($this->available_printers[0]);
478
            }
479
            else
480
            {
481
                trigger_error(_("getJobs: Printer URI is not set: die"), E_USER_WARNING);
482
                self::_putDebug(_("_stringJob: Printer URI is not set: die\n"), 3);
483
                self::_errorLog("getJobs: Printer URI is not set, die", 2);
484
                return FALSE;
485
                }
486
            }
487
488
        if (!isset($this->setup->charset))
489
        {
490
            self::setCharset();
491
        }
492
493
        if (!isset($this->setup->language))
494
        {
495
            self::setLanguage('en_us');
496
        }
497
498
        if (!isset($this->meta->username))
499
        {
500
            self::setUserName();
501
        }
502
503
        if ($limit)
504
        {
505
            $limit = self::_integerBuild($limit);
506
            $this->meta->limit = chr(0x21) // integer
507
                               . self::_giveMeStringLength('limit')
508
                               . 'limit'
509
                               . self::_giveMeStringLength($limit)
510
                               . $limit;
511
        }
512
        else
513
        {
514
            $this->meta->limit = '';
515
        }
516
517
        if ($which_jobs == 'completed')
518
        {
519
                $this->meta->which_jobs = chr(0x44) // keyword
520
                                        . self::_giveMeStringLength('which-jobs')
521
                                        . 'which-jobs'
522
                                        . self::_giveMeStringLength($which_jobs)
523
                                        . $which_jobs;
524
        }
525
        else
526
        {
527
            $this->meta->which_jobs = "";
528
        }
529
530
        if ($my_jobs)
531
        {
532
            $this->meta->my_jobs = chr(0x22) // boolean
533
                                 . self::_giveMeStringLength('my-jobs')
534
                                 . 'my-jobs'
535
                                 . self::_giveMeStringLength(chr(0x01))
536
                                 . chr(0x01);
537
        }
538
        else
539
        {
540
            $this->meta->my_jobs = '';
541
        }
542
543
        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
544
                         . chr(0x00) . chr(0x0A) // Get-Jobs | operation-id
545
                         . $this->meta->operation_id //           request-id
546
                         . chr(0x01) // start operation-attributes | operation-attributes-tag
547
                         . $this->meta->charset
548
                         . $this->meta->language
549
                         . $this->meta->printer_uri
550
                         . $this->meta->username
551
                         . $this->meta->limit
552
                         . $this->meta->which_jobs 
553
                         . $this->meta->my_jobs;
554
       if ($subset)
555
       {
556
            $this->stringjob .=
557
                          chr(0x44) // keyword
558
                         . self::_giveMeStringLength('requested-attributes')
559
                         . 'requested-attributes'
560
                         . self::_giveMeStringLength('job-uri')
561
                         . 'job-uri'
562
                         . chr(0x44) // keyword
563
                         . self::_giveMeStringLength('')
564
                         . ''
565
                         . self::_giveMeStringLength('job-name')
566
                         . 'job-name'
567
                         . chr(0x44) // keyword
568
                         . self::_giveMeStringLength('')
569
                         . ''
570
                         . self::_giveMeStringLength('job-state')
571
                         . 'job-state'
572
                         . chr(0x44) // keyword
573
                         . self::_giveMeStringLength('')
574
                         . ''
575
                         . self::_giveMeStringLength('job-state-reason')
576
                         . 'job-state-reason';
577
        }
578
        else
579
        { // cups 1.4.4 doesn't return much of anything without this
580
            $this->stringjob .=
581
                          chr(0x44) // keyword
582
                         . self::_giveMeStringLength('requested-attributes')
583
                         . 'requested-attributes'
584
                         . self::_giveMeStringLength('all')
585
                         . 'all';
586
        }
587
        $this->stringjob .= chr(0x03); // end-of-attributes | end-of-attributes-tag
588
589
        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
590
591
        self::_putDebug(sprintf(_("getting jobs of %s\n"), $this->printer_uri), 2); 
592
593
        $this->output = $this->stringjob;
594
595
        $post_values = array( "Content-Type" => "application/ipp",
596
                              "Data" => $this->output);
597
598
        if (self::_sendHttp($post_values, $this->paths['jobs']))
599
        {
600
            if (self::_parseServerOutput())
601
            {
602
                self::_parseJobsAttributes();
603
            }
604
        }
605
606
        $this->attributes = &$this->jobs_attributes;
607
608
        if (isset($this->serveroutput) && isset($this->serveroutput->status))
609
        {
610
            $this->status = array_merge($this->status, array($this->serveroutput->status));
611
612
            if ($this->serveroutput->status == "successfull-ok")
613
            {
614
                self::_errorLog(sprintf(_("getting jobs of printer %s: "), $this->printer_uri)
615
                            . $this->serveroutput->status, 3);
616
            }
617
            else
618
            {
619
                 self::_errorLog(sprintf(_("getting jobs of printer %s: "), $this->printer_uri)
620
                                             . $this->serveroutput->status, 1);
621
            }
622
623
            return $this->serveroutput->status;
624
        }
625
626
        $this->status = array_merge($this->status, array("OPERATION FAILED"));
627
        self::_errorLog(date("Y-m-d H:i:s : ")
628
                        . basename($_SERVER['PHP_SELF'])
629
                        . sprintf(
630
                            _("getting jobs of %s : OPERATION FAILED"),
631
                                     $this->printer_uri), 3);
632
633
    return false;
634
    }
635
636
637
    public function getJobAttributes($job_uri, $subset = false, $attributes_group = "all")
638
    {
639
        $this->jobs = array_merge($this->jobs, array(""));
640
        $this->jobs_uri = array_merge($this->jobs_uri, array(""));
641
642
        if (!$job_uri)
643
        {
644
            trigger_error(_("getJobAttributes: Job URI is not set, die."));
645
            return FALSE;
646
            }
647
648
        self::_setOperationId();
649
        $this->parsed = array();
650
        unset($this->printer_attributes);
651
652
        if (!isset($this->setup->uri))
653
        {
654
            $this->getPrinters();
655
            unset($this->jobs[count($this->jobs) - 1]);
656
            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
657
            unset($this->status[count($this->status) - 1]);
658
659
            if (array_key_exists(0, $this->available_printers))
660
            {
661
               self::setPrinterURI($this->available_printers[0]);
662
            }
663
            else
664
            {
665
                trigger_error(_("getJobs: Printer URI is not set: die"), E_USER_WARNING);
666
                self::_putDebug(_("_stringJob: Printer URI is not set: die\n"), 3);
667
                self::_errorLog("getJobs: Printer URI is not set, die", 2);
668
                return FALSE;
669
            }
670
        }
671
672
        if (!isset($this->setup->charset))
673
        {
674
            self::setCharset();
675
        }
676
677
        if (!isset($this->setup->language))
678
        {
679
            self::setLanguage('en_us');
680
        }
681
682
        if (!isset($this->meta->username))
683
        {
684
            self::setUserName();
685
        }
686
687
        $this->meta->job_uri = chr(0x45) // URI
688
                             . self::_giveMeStringLength('job-uri')
689
                             . 'job-uri'
690
                             . self::_giveMeStringLength($job_uri)
691
                             . $job_uri;
692
693
        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
694
                         . chr(0x00) . chr(0x09) // Get-Job-Attributes | operation-id
695
                         . $this->meta->operation_id //           request-id
696
                         . chr(0x01) // start operation-attributes | operation-attributes-tag
697
                         . $this->meta->charset
698
                         . $this->meta->language
699
                         . $this->meta->job_uri
700
                         . $this->meta->username;
701
        if ($subset)
702
        {
703
            $this->stringjob .=
704
                          chr(0x44) // keyword
705
                         . self::_giveMeStringLength('requested-attributes')
706
                         . 'requested-attributes'
707
                         . self::_giveMeStringLength('job-uri')
708
                         . 'job-uri'
709
                         . chr(0x44) // keyword
710
                         . self::_giveMeStringLength('')
711
                         . ''
712
                         . self::_giveMeStringLength('job-name')
713
                         . 'job-name'
714
                         . chr(0x44) // keyword
715
                         . self::_giveMeStringLength('')
716
                         . ''
717
                         . self::_giveMeStringLength('job-state')
718
                         . 'job-state'
719
                         . chr(0x44) // keyword
720
                         . self::_giveMeStringLength('')
721
                         . ''
722
                         . self::_giveMeStringLength('job-state-reason')
723
                         . 'job-state-reason';
724
        }
725
        elseif($attributes_group)
726
        {
727
            switch($attributes_group)
728
            {
729
                case 'job-template':
730
                    break;
731
                case 'job-description':
732
                    break;
733
                case 'all':
734
                    break;
735
                default:
736
                    trigger_error(_('not a valid attribute group: ') . $attributes_group, E_USER_NOTICE);
737
                    $attributes_group = '';
738
                    break;
739
            }
740
            $this->stringjob .=
741
                          chr(0x44) // keyword
742
                         . self::_giveMeStringLength('requested-attributes')
743
                         . 'requested-attributes'
744
                         . self::_giveMeStringLength($attributes_group)
745
                         . $attributes_group;
746
        }
747
        $this->stringjob .= chr(0x03); // end-of-attributes | end-of-attributes-tag
748
749
        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
750
751
        self::_putDebug(sprintf(_("getting jobs of %s\n"), $this->printer_uri), 2); 
752
753
        $this->output = $this->stringjob;
754
755
        $post_values = array( "Content-Type" => "application/ipp",
756
                              "Data" => $this->output);
757
758
        if (self::_sendHttp($post_values, $this->paths['jobs']))
759
        {
760
            if (self::_parseServerOutput())
761
            {
762
                self::_parseJobAttributes();
763
            }
764
        }
765
766
        $this->attributes = &$this->job_attributes;
767
768
        if (isset($this->serveroutput) && isset($this->serveroutput->status))
769
        {
770
            $this->status = array_merge($this->status, array($this->serveroutput->status));
771
772
            if ($this->serveroutput->status == "successfull-ok")
773
            {
774
                self::_errorLog(sprintf(_("getting job attributes for %s: "), $job_uri)
775
                            . $this->serveroutput->status, 3);
776
            }
777
            else
778
            {
779
                 self::_errorLog(sprintf(_("getting job attributes for %s: "), $job_uri)
780
                                             . $this->serveroutput->status, 1);
781
            }
782
783
            return $this->serveroutput->status;
784
        }
785
786
        $this->status = array_merge($this->status, array("OPERATION FAILED"));
787
        self::_errorLog(date("Y-m-d H:i:s : ")
788
                        . basename($_SERVER['PHP_SELF'])
789
                        . sprintf(
790
                            _("getting jobs attributes of %s : OPERATION FAILED"),
791
                                     $job_uri), 3);
792
793
        return false;
794
    }
795
796
    public function getPrinters()
797
    {
798
        // placeholder for vendor extension operation (getAvailablePrinters for CUPS)
799
        $this->jobs = array_merge($this->jobs, array(''));
800
        $this->jobs_uri = array_merge($this->jobs_uri, array(''));
801
        $this->status = array_merge($this->status, array(''));    
802
    }
803
804
    public function generateError($error)
805
    {
806
        switch ($error)
807
        {
808
            case "request_body_malformed":
809
                $this->error_generation->request_body_malformed = chr(0xFF);
810
                break;
811
            default:
812
                true;
813
                break;
814
        }
815
816
        trigger_error(sprintf(_('Setting Error %s'), $error), E_USER_NOTICE);
817
    }
818
    
819
    public function resetError($error)
820
    {
821
        unset($this->error_generation->$error);
822
        trigger_error(sprintf(_('Reset Error %s'), $error), E_USER_NOTICE);
823
    }
824
825
    // SETUP
826
    protected function _setOperationId()
827
    {
828
            $prepend = '';
829
            $this->operation_id += 1;
830
            $this->meta->operation_id = self::_integerBuild($this->operation_id);
831
            self::_putDebug("operation id is: " . $this->operation_id . "\n", 2);
832
    }
833
    
834
    protected function _setJobId()
835
    {
836
837
        $this->meta->jobid += 1;
838
        $prepend = '';
839
        $prepend_length = 4 - strlen($this->meta->jobid);
840
        for ($i = 0; $i < $prepend_length ; $i++)
841
        {
842
            $prepend .= '0';
843
        }
844
845
    return $prepend . $this->meta->jobid;
846
    }
847
    
848
    protected function _setJobUri($job_uri)
849
    {
850
        $this->meta->job_uri = chr(0x45) // type uri
851
                             . chr(0x00) . chr(0x07) // name-length
852
                             . "job-uri"
853
                             //. chr(0x00).chr(strlen($job_uri))
854
                             . self::_giveMeStringLength($job_uri)
855
                             . $job_uri;
856
        
857
        self::_putDebug("job-uri is: " . $job_uri . "\n", 2);
858
    }
859
860
    // RESPONSE PARSING
861
    protected function _parsePrinterAttributes()
862
    {
863
        //if (!preg_match('#successful#',$this->serveroutput->status))
864
        //   return false;
865
866
        $k = -1;
867
        $l = 0;
868
        for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
869
        {
870
            for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j++)
871
            {
872
                if (!empty($this->serveroutput->response[$i][$j]['name']))
873
                {
874
                    $k++;
875
                    $l = 0;
876
                    $this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
877
                    $this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
878
                    $this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
879
                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
880
                }
881
                else
882
                {
883
                    $l++;
884
                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
885
                    }
886
            }
887
        }
888
        $this->serveroutput->response = array();
889
890
        $this->printer_attributes = new \stdClass();
891
        for ($i = 0 ; $i < count($this->parsed) ; $i++)
892
        {
893
                    $name = $this->parsed[$i]['name'];
894
                    $php_name = str_replace('-', '_', $name);
895
                    $type = $this->parsed[$i]['type'];
896
                    $range = $this->parsed[$i]['range'];
897
                    $this->printer_attributes->$php_name = new \stdClass();
898
                    $this->printer_attributes->$php_name->_type = $type;
899
                    $this->printer_attributes->$php_name->_range = $range;
900
                    for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j++)
901
                    {
902
                $value = $this->parsed[$i][$j];
903
                $index = '_value' . $j;
904
                $this->printer_attributes->$php_name->$index = $value;
905
                        }
906
                    }
907
908
        $this->parsed = array();
909
    }
910
911
    protected function _parseJobsAttributes()
912
    {
913
        //if ($this->serveroutput->status != "successfull-ok")
914
        //    return false;
915
916
        $job = -1;
917
        $l = 0;
918
        for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
919
        {
920
            if ($this->serveroutput->response[$i]['attributes'] == "job-attributes")
921
            {
922
                $job++;
923
            }
924
            $k = -1; 
925
            for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j++)
926
            {
927
                if (!empty($this->serveroutput->response[$i][$j]['name']))
928
                {
929
                    $k++;
930
                    $l = 0;
931
                    $this->parsed[$job][$k]['range'] = $this->serveroutput->response[$i]['attributes'];
932
                    $this->parsed[$job][$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
933
                    $this->parsed[$job][$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
934
                    $this->parsed[$job][$k][$l] = $this->serveroutput->response[$i][$j]['value'];
935
                }
936
                else
937
                {
938
                    $l++;
939
                    $this->parsed[$job][$k][$l] = $this->serveroutput->response[$i][$j]['value'];
940
                }
941
            }
942
        }
943
944
        $this->serveroutput->response = array();
945
        $this->jobs_attributes = new \stdClass();
946
        for ($job_nbr = 0 ; $job_nbr <= $job ; $job_nbr++)
947
        {
948
            $job_index = "job_" . $job_nbr;
949
            $this->jobs_attributes->$job_index = new \stdClass();
950
            for ($i = 0 ; $i < count($this->parsed[$job_nbr]) ; $i++)
951
            {
952
                $name = $this->parsed[$job_nbr][$i]['name'];
953
                $php_name = str_replace('-', '_', $name);
954
                $type = $this->parsed[$job_nbr][$i]['type'];
955
                $range = $this->parsed[$job_nbr][$i]['range'];
956
                $this->jobs_attributes->$job_index->$php_name = new \stdClass();
957
                $this->jobs_attributes->$job_index->$php_name->_type = $type;
958
                $this->jobs_attributes->$job_index->$php_name->_range = $range;
959
                for ($j = 0 ; $j < (count($this->parsed[$job_nbr][$i]) - 3) ; $j++)
960
                {
961
                    // This causes incorrect parsing of integer job attributes.
962
                    // 2010-08-16
963
                    // bpkroth
964
                    // $value = self::_interpretAttribute($name,$type,$this->parsed[$job_nbr][$i][$j]);
965
                    $value = $this->parsed[$job_nbr][$i][$j];
966
                    $index = '_value' . $j;
967
                    $this->jobs_attributes->$job_index->$php_name->$index = $value;
968
                }
969
            }
970
        }
971
972
        $this->parsed = array();
973
    }
974
975
    protected function _readAttribute($attributes_type)
976
    {
977
        $tag = ord($this->serveroutput->body[$this->_parsing->offset]);
978
979
        $this->_parsing->offset += 1;
980
        $j = $this->index;
981
982
        $tag = self::_readTag($tag);
983
984
        switch ($tag)
985
        {
986
            case "begCollection": //RFC3382 (BLIND CODE)
987
                if ($this->end_collection)
988
                {
989
                    $this->index--;
990
                }
991
                $this->end_collection = false;
992
                $this->serveroutput->response[$attributes_type][$j]['type'] = "collection";
993
                self::_putDebug("tag is: begCollection\n");
994
                self::_readAttributeName($attributes_type, $j);
995
                if (!$this->serveroutput->response[$attributes_type][$j]['name'])
996
                { // it is a multi-valued collection
997
                    $this->collection_depth++;
998
                    $this->index--;
999
                    $this->collection_nbr[$this->collection_depth]++;
1000
                }
1001
                else
1002
                {
1003
                    $this->collection_depth++;
1004
                    if ($this->collection_depth == 0)
1005
                    {
1006
                        $this->collection = (object) 'collection';
1007
                    }
1008
                    if (array_key_exists($this->collection_depth, $this->collection_nbr))
1009
                    {
1010
                        $this->collection_nbr[$this->collection_depth]++;
1011
                    }
1012
                    else
1013
                    {
1014
                        $this->collection_nbr[$this->collection_depth] = 0;
1015
                    }
1016
                    unset($this->end_collection);
1017
                }
1018
                self::_readValue("begCollection", $attributes_type, $j);
1019
                break;
1020
            case "endCollection": //RFC3382 (BLIND CODE)
1021
                $this->serveroutput->response[$attributes_type][$j]['type'] = "collection";
1022
                self::_putDebug("tag is: endCollection\n");
1023
                self::_readAttributeName($attributes_type, $j, 0);
1024
                self::_readValue('name', $attributes_type, $j, 0);
1025
                $this->collection_depth--;
1026
                $this->collection_key[$this->collection_depth] = 0;
1027
                $this->end_collection = true;
1028
                break;
1029
            case "memberAttrName": // RFC3382 (BLIND CODE)
1030
                $this->serveroutput->response[$attributes_type][$j]['type'] = "memberAttrName";
1031
                $this->index-- ;
1032
                self::_putDebug("tag is: memberAttrName\n");
1033
                self::_readCollection($attributes_type, $j);
1034
                break;
1035
1036
            default:
1037
                $this->collection_depth = -1;
1038
                $this->collection_key = array();
1039
                $this->collection_nbr = array();
1040
                $this->serveroutput->response[$attributes_type][$j]['type'] = $tag;
1041
                self::_putDebug("tag is: $tag\n");
1042
                $attribute_name = self::_readAttributeName($attributes_type, $j);
1043
                if (!$attribute_name)
1044
                {
1045
                    $attribute_name = $this->attribute_name;
1046
                }
1047
                else
1048
                {
1049
                    $this->attribute_name = $attribute_name;
1050
                }
1051
                $value = self::_readValue($tag, $attributes_type, $j);
1052
                $this->serveroutput->response[$attributes_type][$j]['value'] = 
1053
                self::_interpretAttribute($attribute_name, $tag, $this->serveroutput->response[$attributes_type][$j]['value']);
1054
                break;
1055
        }
1056
        return;
1057
    }
1058
1059
    protected function _readTag($tag)
1060
    {
1061
        switch ($tag)
1062
        {
1063
            case 0x10:
1064
                $tag = "unsupported";
1065
                break;
1066
            case 0x11:
1067
                $tag = "reserved for 'default'";
1068
                break;
1069
            case 0x12:
1070
                $tag = "unknown";
1071
                break;
1072
            case 0x13:
1073
                $tag = "no-value";
1074
                break;
1075
            case 0x15: // RFC 3380
1076
                $tag = "not-settable";
1077
                break;
1078
            case 0x16: // RFC 3380
1079
                $tag = "delete-attribute";
1080
                break;
1081
            case 0x17: // RFC 3380
1082
                $tag = "admin-define";
1083
                break;
1084
            case 0x20:
1085
                $tag = "IETF reserved (generic integer)";
1086
                break;
1087
            case 0x21:
1088
                $tag = "integer";
1089
                break;
1090
            case 0x22:
1091
                $tag = "boolean";
1092
                break;
1093
            case 0x23:
1094
                $tag = "enum";
1095
                break;
1096
            case 0x30:
1097
                $tag = "octetString";
1098
                break;
1099
            case 0x31:
1100
                $tag = "datetime";
1101
                break;
1102
            case 0x32:
1103
                $tag = "resolution";
1104
                break;
1105
            case 0x33:
1106
                $tag = "rangeOfInteger";
1107
                break;
1108
            case 0x34: //RFC3382 (BLIND CODE)
1109
                $tag = "begCollection";
1110
                break;
1111
            case 0x35:
1112
                $tag = "textWithLanguage";
1113
                break;
1114
            case 0x36:
1115
                $tag = "nameWithLanguage";
1116
                break;
1117
            case 0x37: //RFC3382 (BLIND CODE)
1118
                $tag = "endCollection";
1119
                break;
1120
            case 0x40:
1121
                $tag = "IETF reserved text string";
1122
                break;
1123
            case 0x41:
1124
                $tag = "textWithoutLanguage";
1125
                break;
1126
            case 0x42:
1127
                $tag = "nameWithoutLanguage";
1128
                break;
1129
            case 0x43:
1130
                $tag = "IETF reserved for future";
1131
                break;
1132
            case 0x44:
1133
                $tag = "keyword";
1134
                break;
1135
            case 0x45:
1136
                $tag = "uri";
1137
                break;
1138
            case 0x46:
1139
                $tag = "uriScheme";
1140
                break;
1141
            case 0x47:
1142
                $tag = "charset";
1143
                break;
1144
            case 0x48:
1145
                $tag = "naturalLanguage";
1146
                break;
1147
            case 0x49:
1148
                $tag = "mimeMediaType";
1149
                break;
1150
            case 0x4A: // RFC3382 (BLIND CODE)
1151
                $tag = "memberAttrName";
1152
                break;
1153
            case 0x7F:
1154
                $tag = "extended type";
1155
                break;
1156
            default:
1157
                if ($tag >= 0x14 && $tag < 0x15 && $tag > 0x17 && $tag <= 0x1f) 
1158
                {
1159
                    $tag = "out-of-band";
1160
                }
1161
                elseif (0x24 <= $tag && $tag <= 0x2f) 
1162
                {
1163
                    $tag = "new integer type";
1164
                }
1165
                elseif (0x38 <= $tag && $tag <= 0x3F) 
1166
                {
1167
                    $tag = "new octet-stream type";
1168
                }
1169
                elseif (0x4B <= $tag && $tag <= 0x5F) 
1170
                {
1171
                    $tag = "new character string type";
1172
                }
1173
                elseif ((0x60 <= $tag && $tag < 0x7f) || $tag >= 0x80)
1174
                {
1175
                    $tag = "IETF reserved for future";
1176
                }
1177
                else
1178
                {
1179
                    $tag = sprintf("UNKNOWN: 0x%x (%u)", $tag, $tag);
1180
                }
1181
                break;                                                            
1182
        }
1183
1184
        return $tag; 
1185
    }
1186
1187
    protected function _readCollection($attributes_type, $j)
1188
    {
1189
        $name_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1190
                     +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1191
1192
        $this->_parsing->offset += 2;
1193
1194
        self::_putDebug("Collection name_length " . $name_length . "\n");
1195
1196
        $name = '';
1197
        for ($i = 0; $i < $name_length; $i++)
1198
        {
1199
            $name .= $this->serveroutput->body[$this->_parsing->offset];
1200
            $this->_parsing->offset += 1;
1201
            if ($this->_parsing->offset > strlen($this->serveroutput->body))
1202
            {
1203
                return;
1204
            }
1205
        }
1206
1207
        $collection_name = $name;
1208
1209
        $name_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1210
                     +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1211
        $this->_parsing->offset += 2;
1212
1213
        self::_putDebug("Attribute name_length " . $name_length . "\n");
1214
1215
        $name = '';
1216
        for ($i = 0; $i < $name_length; $i++)
1217
        {
1218
            $name .= $this->serveroutput->body[$this->_parsing->offset];
1219
            $this->_parsing->offset += 1;
1220
            if ($this->_parsing->offset > strlen($this->serveroutput->body))
1221
            {
1222
                return;
1223
            }
1224
        }
1225
1226
        $attribute_name = $name;
1227
        if ($attribute_name == "")
1228
        {
1229
            $attribute_name = $this->last_attribute_name;
1230
            $this->collection_key[$this->collection_depth]++;
1231
        }
1232
        else
1233
        {
1234
            $this->collection_key[$this->collection_depth] = 0;
1235
        }
1236
        $this->last_attribute_name = $attribute_name;
1237
1238
        self::_putDebug("Attribute name " . $name . "\n");
1239
1240
        $tag = self::_readTag(ord($this->serveroutput->body[$this->_parsing->offset]));
1241
        $this->_parsing->offset++;
1242
1243
        $type = $tag;
1244
1245
        $name_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1246
                     +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1247
        $this->_parsing->offset += 2;
1248
1249
        self::_putDebug("Collection2 name_length " . $name_length . "\n");
1250
1251
        $name = '';
1252
        for ($i = 0; $i < $name_length; $i++)
1253
        {
1254
            $name .= $this->serveroutput->body[$this->_parsing->offset];
1255
            $this->_parsing->offset += 1;
1256
            if ($this->_parsing->offset > strlen($this->serveroutput->body))
1257
            {
1258
                return;
1259
            }
1260
        }
1261
1262
        $collection_value = $name;
1263
        $value_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1264
                      +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1265
1266
        self::_putDebug("Collection value_length " . $this->serveroutput->body[ $this->_parsing->offset]
1267
                                       . $this->serveroutput->body[$this->_parsing->offset + 1]
1268
                                       . ": "
1269
                                       . $value_length
1270
                                       . " ");
1271
1272
        $this->_parsing->offset += 2;
1273
1274
        $value = '';
1275
        for ($i = 0; $i < $value_length; $i++)
1276
        {
1277
            if ($this->_parsing->offset >= strlen($this->serveroutput->body))
1278
            {
1279
                return;
1280
            }
1281
            $value .= $this->serveroutput->body[$this->_parsing->offset];
1282
            $this->_parsing->offset += 1;
1283
        }
1284
1285
        $object = &$this->collection;
1286
        for ($i = 0 ; $i <= $this->collection_depth ; $i++)
1287
        {
1288
            $indice = "_indice" . $this->collection_nbr[$i];
1289
            if (!isset($object->$indice))
1290
            {
1291
                $object->$indice = (object) 'indice';
1292
            }
1293
            $object = &$object->$indice;
1294
        }
1295
1296
        $value_key = "_value" . $this->collection_key[$this->collection_depth];
1297
        $col_name_key = "_collection_name" . $this->collection_key[$this->collection_depth];
1298
        $col_val_key = "_collection_value" . $this->collection_key[$this->collection_depth];
1299
1300
        $attribute_value = self::_interpretAttribute($attribute_name, $tag, $value);
1301
        $attribute_name = str_replace('-', '_', $attribute_name);
1302
1303
        self::_putDebug(sprintf("Value: %s\n", $value));
1304
        $object->$attribute_name->_type = $type;
1305
        $object->$attribute_name->$value_key = $attribute_value;
1306
        $object->$attribute_name->$col_name_key = $collection_name;
1307
        $object->$attribute_name->$col_val_key = $collection_value;
1308
1309
        $this->serveroutput->response[$attributes_type][$j]['value'] = $this->collection;
1310
    }
1311
1312
    protected function _readAttributeName($attributes_type, $j, $write = 1)
1313
    {
1314
        $name_length = ord($this->serveroutput->body[ $this->_parsing->offset]) *  256
1315
                     +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1316
        $this->_parsing->offset += 2;
1317
1318
        self::_putDebug("name_length " . $name_length . "\n");
1319
1320
        $name = '';
1321
        for ($i = 0; $i < $name_length; $i++)
1322
        {
1323
            if ($this->_parsing->offset >= strlen($this->serveroutput->body))
1324
            {
1325
                return;
1326
            }
1327
            $name .= $this->serveroutput->body[$this->_parsing->offset];
1328
            $this->_parsing->offset += 1;
1329
        }
1330
1331
        if($write)
1332
        {
1333
            $this->serveroutput->response[$attributes_type][$j]['name'] = $name;
1334
        }
1335
1336
        self::_putDebug("name " . $name . "\n");
1337
1338
        return $name;   
1339
    }
1340
1341
    protected function _readValue($type, $attributes_type, $j, $write = 1)
1342
    {
1343
        $value_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1344
                      +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1345
        
1346
        self::_putDebug("value_length " . $this->serveroutput->body[ $this->_parsing->offset]
1347
                                       . $this->serveroutput->body[$this->_parsing->offset + 1]
1348
                                       . ": "
1349
                                       . $value_length
1350
                                       . " ");
1351
1352
        $this->_parsing->offset += 2;
1353
1354
        $value = '';
1355
        for ($i = 0; $i < $value_length; $i++)
1356
        {
1357
            if ($this->_parsing->offset >= strlen($this->serveroutput->body))
1358
            {
1359
                return;
1360
            }
1361
            $value .= $this->serveroutput->body[$this->_parsing->offset];
1362
            $this->_parsing->offset += 1;
1363
            }
1364
1365
        self::_putDebug(sprintf("Value: %s\n", $value));
1366
1367
        if ($write)
1368
        {
1369
            $this->serveroutput->response[$attributes_type][$j]['value'] = $value;
1370
        }
1371
1372
        return $value;
1373
    }
1374
1375
    protected function _parseAttributes()
1376
    {
1377
        $k = -1;
1378
        $l = 0;
1379
        for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
1380
        {
1381
            for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j++)
1382
            {
1383
                if (!empty($this->serveroutput->response[$i][$j]['name']))
1384
                {
1385
                    $k++;
1386
                    $l = 0;
1387
                    $this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
1388
                    $this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
1389
                    $this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
1390
                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1391
                }
1392
                else
1393
                {
1394
                    $l++;
1395
                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1396
                }
1397
            }
1398
        }
1399
        $this->serveroutput->response = array();
1400
        $this->attributes  = new \stdClass();
1401
        for ($i = 0 ; $i < count($this->parsed) ; $i++)
1402
        {
1403
                    $name = $this->parsed[$i]['name'];
1404
                    $php_name = str_replace('-', '_', $name);
1405
                    $type = $this->parsed[$i]['type'];
1406
                    $range = $this->parsed[$i]['range'];
1407
                    $this->attributes->$php_name = new \stdClass();
1408
                    $this->attributes->$php_name->_type = $type;
1409
                    $this->attributes->$php_name->_range = $range;
1410
                    for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j++)
1411
                    {
1412
                $value = $this->parsed[$i][$j];
1413
                $index = '_value' . $j;
1414
                $this->attributes->$php_name->$index = $value;
1415
                        }
1416
                    }
1417
1418
        $this->parsed = array();
1419
    }
1420
1421
    protected function _parseJobAttributes()
1422
    {
1423
        //if (!preg_match('#successful#',$this->serveroutput->status))
1424
        //    return false;
1425
        $k = -1;
1426
        $l = 0;
1427
        for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
1428
        {
1429
            for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j++)
1430
            {
1431
                if (!empty($this->serveroutput->response[$i][$j]['name']))
1432
                {
1433
                    $k++;
1434
                    $l = 0;
1435
                    $this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
1436
                    $this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
1437
                    $this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
1438
                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1439
                }
1440
                else
1441
                {
1442
                    $l++;
1443
                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1444
                }
1445
            }
1446
        }
1447
1448
        $this->serveroutput->response = array();
1449
1450
        $this->job_attributes = new \stdClass();
1451
        for ($i = 0 ; $i < count($this->parsed) ; $i++)
1452
        {
1453
                    $name = $this->parsed[$i]['name'];
1454
                    $php_name = str_replace('-', '_', $name);
1455
                    $type = $this->parsed[$i]['type'];
1456
                    $range = $this->parsed[$i]['range'];
1457
                    $this->job_attributes->$php_name = new \stdClass();
1458
                    $this->job_attributes->$php_name->_type = $type;
1459
                    $this->job_attributes->$php_name->_range = $range;
1460
                    for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j++)
1461
                    {
1462
                $value = $this->parsed[$i][$j];
1463
                $index = '_value' . $j;
1464
                $this->job_attributes->$php_name->$index = $value;
1465
                        }
1466
                    }
1467
1468
        $this->parsed = array();
1469
    }
1470
1471
    protected function _interpretAttribute($attribute_name, $type, $value)
1472
    {
1473
        switch ($type)
1474
        {
1475
            case "integer":
1476
                $value = self::_interpretInteger($value);
1477
                break;
1478
            case "rangeOfInteger":
1479
                $value = self::_interpretRangeOfInteger($value);
1480
                break;
1481
            case 'boolean':
1482
                $value = ord($value);
1483
                if ($value == 0x00)
1484
                {
1485
                    $value = 'false';
1486
                }
1487
                else
1488
                {
1489
                    $value = 'true';
1490
                }
1491
                break;
1492
            case 'datetime':
1493
                $value = self::_interpretDateTime($value);
1494
                break;
1495
            case 'enum':
1496
                $value = $this->_interpretEnum($attribute_name, $value); // must be overwritten by children
1497
                break;
1498
            case 'resolution':
1499
                $unit = $value[8];
1500
                $value = self::_interpretRangeOfInteger(substr($value, 0, 8));
1501
                switch($unit)
1502
                {
1503
                    case chr(0x03):
1504
                        $unit = "dpi";
1505
                        break;
1506
                    case chr(0x04):
1507
                        $unit = "dpc";
1508
                        break;
1509
                    }
1510
                $value = $value . " " . $unit;
1511
                break;
1512
            default:
1513
                break;
1514
        }
1515
        return $value;
1516
    }
1517
1518
    protected function _interpretRangeOfInteger($value)
1519
    {
1520
        $value_parsed = 0;
1521
        $integer1 = $integer2 = 0;
1522
1523
        $halfsize = strlen($value) / 2;
1524
1525
        $integer1 = self::_interpretInteger(substr($value, 0, $halfsize));
1526
        $integer2 = self::_interpretInteger(substr($value, $halfsize, $halfsize));
1527
1528
        $value_parsed = sprintf('%s-%s', $integer1, $integer2);
1529
1530
        return $value_parsed;
1531
    }
1532
1533
    protected function _interpretDateTime($date)
1534
    {
1535
        $year = self::_interpretInteger(substr($date, 0, 2));
1536
        $month =  self::_interpretInteger(substr($date, 2, 1));
1537
        $day =  self::_interpretInteger(substr($date, 3, 1));
1538
        $hour =  self::_interpretInteger(substr($date, 4, 1));
1539
        $minute =  self::_interpretInteger(substr($date, 5, 1));
1540
        $second =  self::_interpretInteger(substr($date, 6, 1));
1541
        $direction = substr($date, 8, 1);
1542
        $hours_from_utc = self::_interpretInteger(substr($date, 9, 1));
1543
        $minutes_from_utc = self::_interpretInteger(substr($date, 10, 1));
1544
1545
        $date = sprintf('%s-%s-%s %s:%s:%s %s%s:%s', $year, $month, $day, $hour, $minute, $second, $direction, $hours_from_utc, $minutes_from_utc);
1546
1547
        return $date;
1548
    }
1549
1550
    protected function _interpretEnum($attribute_name, $value)
1551
    {
1552
        $value_parsed = self::_interpretInteger($value);
1553
1554
        switch ($attribute_name)
1555
        {
1556
            case 'job-state':
1557
                switch ($value_parsed)
1558
                {
1559
                    case 0x03:
1560
                        $value = 'pending';
1561
                        break;
1562
                    case 0x04:
1563
                        $value = 'pending-held';
1564
                        break;
1565
                    case 0x05:
1566
                        $value = 'processing';
1567
                        break;
1568
                    case 0x06:
1569
                        $value = 'processing-stopped';
1570
                        break;
1571
                    case 0x07:
1572
                        $value = 'canceled';
1573
                        break;
1574
                    case 0x08:
1575
                        $value = 'aborted';
1576
                        break;
1577
                    case 0x09:
1578
                        $value = 'completed';
1579
                        break;
1580
                }
1581
                if ($value_parsed > 0x09)
1582
                {
1583
                    $value = sprintf('Unknown(IETF standards track "job-state" reserved): 0x%x', $value_parsed);
1584
                }
1585
                break;
1586
            case 'print-quality':
1587
            case 'print-quality-supported':
1588
            case 'print-quality-default':
1589
                switch ($value_parsed)
1590
                {
1591
                    case 0x03:
1592
                        $value = 'draft';
1593
                        break;
1594
                    case 0x04:
1595
                        $value = 'normal';
1596
                        break;
1597
                    case 0x05:
1598
                        $value = 'high';
1599
                        break;
1600
                    }
1601
                break;
1602
            case 'printer-state':
1603
                switch ($value_parsed)
1604
                {
1605
                    case 0x03:
1606
                        $value = 'idle';
1607
                        break;
1608
                    case 0x04:
1609
                        $value = 'processing';
1610
                        break;
1611
                    case 0x05:
1612
                        $value = 'stopped';
1613
                        break;
1614
                }
1615
                if ($value_parsed > 0x05)
1616
                {
1617
                    $value = sprintf('Unknown(IETF standards track "printer-state" reserved): 0x%x', $value_parsed);
1618
                }
1619
                break;
1620
1621
            case 'operations-supported':
1622
                switch($value_parsed)
1623
                {
1624
                    case 0x0000:
1625
                    case 0x0001:
1626
                        $value = sprintf('Unknown(reserved) : %s', ord($value));
1627
                        break;
1628
                    case 0x0002:
1629
                        $value = 'Print-Job';
1630
                        break;
1631
                    case 0x0003:
1632
                        $value = 'Print-URI';
1633
                        break;
1634
                    case 0x0004:
1635
                        $value = 'Validate-Job';
1636
                        break;
1637
                    case 0x0005:
1638
                        $value = 'Create-Job';
1639
                        break;
1640
                    case 0x0006:
1641
                        $value = 'Send-Document';
1642
                        break;
1643
                    case 0x0007:
1644
                        $value = 'Send-URI';
1645
                        break;
1646
                    case 0x0008:
1647
                        $value = 'Cancel-Job';
1648
                        break;
1649
                    case 0x0009:
1650
                        $value = 'Get-Job-Attributes';
1651
                        break;
1652
                    case 0x000A:
1653
                        $value = 'Get-Jobs';
1654
                        break;
1655
                    case 0x000B:
1656
                        $value = 'Get-Printer-Attributes';
1657
                        break;
1658
                    case 0x000C:
1659
                        $value = 'Hold-Job';
1660
                        break;
1661
                    case 0x000D:
1662
                        $value = 'Release-Job';
1663
                        break;
1664
                    case 0x000E:
1665
                        $value = 'Restart-Job';
1666
                        break;
1667
                    case 0x000F:
1668
                        $value = 'Unknown(reserved for a future operation)';
1669
                        break;
1670
                    case 0x0010:
1671
                        $value = 'Pause-Printer';
1672
                        break;
1673
                    case 0x0011:
1674
                        $value = 'Resume-Printer';
1675
                        break;
1676
                    case 0x0012:
1677
                        $value = 'Purge-Jobs';
1678
                        break;
1679
                    case 0x0013:
1680
                        $value = 'Set-Printer-Attributes'; // RFC3380
1681
                        break;
1682
                    case 0x0014:
1683
                        $value = 'Set-Job-Attributes'; // RFC3380
1684
                        break;
1685
                    case 0x0015:
1686
                        $value = 'Get-Printer-Supported-Values'; // RFC3380
1687
                        break;
1688
                    case 0x0016:
1689
                        $value = 'Create-Printer-Subscriptions';
1690
                        break;
1691
                    case 0x0017:
1692
                        $value = 'Create-Job-Subscriptions';
1693
                        break;
1694
                    case 0x0018:
1695
                        $value = 'Get-Subscription-Attributes';
1696
                        break;
1697
                    case 0x0019:
1698
                        $value = 'Get-Subscriptions';
1699
                        break;
1700
                    case 0x001A:
1701
                        $value = 'Renew-Subscription';
1702
                        break;
1703
                    case 0x001B:
1704
                        $value = 'Cancel-Subscription';
1705
                        break;
1706
                    case 0x001C:
1707
                        $value = 'Get-Notifications';
1708
                        break;
1709
                    case 0x001D:
1710
                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x', ord($value));
1711
                        break;
1712
                    case 0x001E:
1713
                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x', ord($value));
1714
                        break;
1715
                    case 0x001F:
1716
                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x', ord($value));
1717
                        break;
1718
                    case 0x0020:
1719
                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x', ord($value));
1720
                        break;
1721
                    case 0x0021:
1722
                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x', ord($value));
1723
                        break;
1724
                    case 0x0022: 
1725
                        $value = 'Enable-Printer';
1726
                        break;
1727
                    case 0x0023: 
1728
                        $value = 'Disable-Printer';
1729
                        break;
1730
                    case 0x0024: 
1731
                        $value = 'Pause-Printer-After-Current-Job';
1732
                        break;
1733
                    case 0x0025: 
1734
                        $value = 'Hold-New-Jobs';
1735
                        break;
1736
                    case 0x0026: 
1737
                        $value = 'Release-Held-New-Jobs';
1738
                        break;
1739
                    case 0x0027: 
1740
                        $value = 'Deactivate-Printer';
1741
                        break;
1742
                    case 0x0028: 
1743
                        $value = 'Activate-Printer';
1744
                        break;
1745
                    case 0x0029: 
1746
                        $value = 'Restart-Printer';
1747
                        break;
1748
                    case 0x002A: 
1749
                        $value = 'Shutdown-Printer';
1750
                        break;
1751
                    case 0x002B: 
1752
                        $value = 'Startup-Printer';
1753
                        break;
1754
                }
1755
                if ($value_parsed > 0x002B && $value_parsed <= 0x3FFF)
1756
                {
1757
                    $value = sprintf('Unknown(IETF standards track operations reserved): 0x%x', $value_parsed);
1758
                }
1759
                elseif ($value_parsed >= 0x4000 && $value_parsed <= 0x8FFF)
1760
                {
1761
                    if (method_exists($this, '_getEnumVendorExtensions'))
1762
                    {
1763
                        $value = $this->_getEnumVendorExtensions($value_parsed);
1764
                    }
1765
                    else
1766
                    {
1767
                        $value = sprintf('Unknown(Vendor extension for operations): 0x%x', $value_parsed);
1768
                    }
1769
                }
1770
                elseif ($value_parsed > 0x8FFF)
1771
                {
1772
                    $value = sprintf('Unknown operation (should not exists): 0x%x', $value_parsed);
1773
                }
1774
1775
                break;
1776
            case 'finishings':
1777
            case 'finishings-default':
1778
            case 'finishings-supported':
1779
                switch ($value_parsed)
1780
                {
1781
                    case 3:
1782
                        $value = 'none';
1783
                        break;
1784
                    case 4:
1785
                        $value = 'staple';
1786
                        break;
1787
                    case 5:
1788
                        $value = 'punch';
1789
                        break;
1790
                    case 6:
1791
                        $value = 'cover';
1792
                        break;
1793
                    case 7:
1794
                        $value = 'bind';
1795
                        break;
1796
                    case 8:
1797
                        $value = 'saddle-stitch';
1798
                        break;
1799
                    case 9:
1800
                        $value = 'edge-stitch';
1801
                        break;
1802
                    case 20:
1803
                        $value = 'staple-top-left';
1804
                        break;
1805
                    case 21:
1806
                        $value = 'staple-bottom-left';
1807
                        break;
1808
                    case 22:
1809
                        $value = 'staple-top-right';
1810
                        break;
1811
                    case 23:
1812
                        $value = 'staple-bottom-right';
1813
                        break;
1814
                    case 24:
1815
                        $value = 'edge-stitch-left';
1816
                        break;
1817
                    case 25:
1818
                        $value = 'edge-stitch-top';
1819
                        break;
1820
                    case 26:
1821
                        $value = 'edge-stitch-right';
1822
                        break;
1823
                    case 27:
1824
                        $value = 'edge-stitch-bottom';
1825
                        break;
1826
                    case 28:
1827
                        $value = 'staple-dual-left';
1828
                        break;
1829
                    case 29:
1830
                        $value = 'staple-dual-top';
1831
                        break;
1832
                    case 30:
1833
                        $value = 'staple-dual-right';
1834
                        break;
1835
                    case 31:
1836
                        $value = 'staple-dual-bottom';
1837
                        break;
1838
                }
1839
                if ($value_parsed > 31)
1840
                {
1841
                    $value = sprintf('Unknown(IETF standards track "finishing" reserved): 0x%x', $value_parsed);
1842
                }
1843
                break;
1844
1845
            case 'orientation-requested':
1846
            case 'orientation-requested-supported':
1847
            case 'orientation-requested-default':
1848
                switch ($value_parsed)
1849
                {
1850
                    case 0x03:
1851
                        $value = 'portrait';
1852
                        break;
1853
                    case 0x04:
1854
                        $value = 'landscape';
1855
                        break;
1856
                    case 0x05:
1857
                        $value = 'reverse-landscape';
1858
                        break;
1859
                    case 0x06:
1860
                        $value = 'reverse-portrait';
1861
                        break;
1862
                }
1863
                if ($value_parsed > 0x06)
1864
                {
1865
                    $value = sprintf('Unknown(IETF standards track "orientation" reserved): 0x%x', $value_parsed);
1866
                }
1867
                break;
1868
1869
            default:
1870
                break;
1871
        }
1872
        return $value;
1873
    }
1874
1875
    protected function _getJobId()
1876
    {
1877
        if (!isset($this->serveroutput->response))
1878
        {
1879
            $this->jobs = array_merge($this->jobs, array('NO JOB'));
1880
        }
1881
1882
        $jobfinded = false;
1883
        for ($i = 0 ; (!$jobfinded && array_key_exists($i, $this->serveroutput->response)) ; $i++)
1884
        {
1885
            if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
1886
            {
1887
                for ($j = 0 ; array_key_exists($j, $this->serveroutput->response[$i]) ; $j++)
1888
                {
1889
                    if ($this->serveroutput->response[$i][$j]['name'] == "job-id")
1890
                    {
1891
                        $this->last_job = $this->serveroutput->response[$i][$j]['value'];
1892
                        $this->jobs = array_merge($this->jobs, array($this->serveroutput->response[$i][$j]['value']));
1893
                        return;
1894
                    }
1895
                }
1896
            }
1897
        }
1898
    }
1899
1900
    protected function _getJobUri()
1901
    {
1902
        if (!isset($this->jobs_uri))
1903
        {
1904
            $this->jobs_uri = array();
1905
        }
1906
1907
        $jobfinded = false;
1908
        for ($i = 0 ; (!$jobfinded && array_key_exists($i, $this->serveroutput->response)) ; $i++)
1909
        {
1910
            if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
1911
            {
1912
                for ($j = 0 ; array_key_exists($j, $this->serveroutput->response[$i]) ; $j++)
1913
                {
1914
                    if ($this->serveroutput->response[$i][$j]['name'] == "job-uri")
1915
                    {
1916
                        $this->last_job = $this->serveroutput->response[$i][$j]['value'];
1917
                        $this->jobs_uri = array_merge($this->jobs_uri, array($this->last_job));
1918
                        return;
1919
                    }
1920
                }
1921
            }
1922
        }
1923
        $this->last_job = '';
1924
    }
1925
1926
    protected function _parseResponse()
1927
    {
1928
        $j = -1;
1929
        $this->index = 0;
1930
        for ($i = $this->_parsing->offset; $i < strlen($this->serveroutput->body) ; $i = $this->_parsing->offset)
1931
        {
1932
            $tag = ord($this->serveroutput->body[$this->_parsing->offset]);
1933
1934
            if ($tag > 0x0F)
1935
            {
1936
                self::_readAttribute($j);
1937
                $this->index++;
1938
                continue;
1939
            }
1940
1941
            switch ($tag)
1942
            {
1943
                case 0x01:
1944
                    $j += 1;
1945
                    $this->serveroutput->response[$j]['attributes'] = "operation-attributes";
1946
                    $this->index = 0;
1947
                    $this->_parsing->offset += 1;
1948
                    break;
1949
                case 0x02:
1950
                    $j += 1;
1951
                    $this->serveroutput->response[$j]['attributes'] = "job-attributes";
1952
                    $this->index = 0;
1953
                    $this->_parsing->offset += 1;
1954
                    break;
1955
                case 0x03:
1956
                    $j += 1;
1957
                    $this->serveroutput->response[$j]['attributes'] = "end-of-attributes";
1958
                    self::_putDebug("tag is: " . $this->serveroutput->response[$j]['attributes'] . "\n");
1959
                    if ($this->alert_on_end_tag === 1)
1960
                    {
1961
                        echo "END tag OK<br />";
1962
                    }
1963
                    $this->response_completed[(count($this->response_completed) - 1)] = "completed";
1964
                    return;
1965
                case 0x04:
1966
                    $j += 1;
1967
                    $this->serveroutput->response[$j]['attributes'] = "printer-attributes";
1968
                    $this->index = 0;
1969
                    $this->_parsing->offset += 1;
1970
                    break;
1971
                case 0x05:
1972
                    $j += 1;
1973
                    $this->serveroutput->response[$j]['attributes'] = "unsupported-attributes";
1974
                    $this->index = 0;
1975
                    $this->_parsing->offset += 1;
1976
                    break;
1977
                default:
1978
                    $j += 1;
1979
                    $this->serveroutput->response[$j]['attributes'] = sprintf(_("0x%x (%u) : attributes tag Unknown (reserved for future versions of IPP"), $tag, $tag);
1980
                    $this->index = 0;
1981
                    $this->_parsing->offset += 1;
1982
                    break;
1983
            }
1984
1985
            self::_putDebug("tag is: " . $this->serveroutput->response[$j]['attributes'] . "\n\n\n");
1986
        }
1987
        return;
1988
    }
1989
1990
    /*
1991
    // NOTICE : HAVE TO READ AGAIN RFC 2911 TO SEE IF IT IS PART OF SERVER'S RESPONSE (CUPS DO NOT)
1992
1993
    protected function _getPrinterUri () {
1994
1995
        for ($i = 0 ; (array_key_exists($i,$this->serveroutput->response)) ; $i ++)
1996
            if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
1997
                for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
1998
                    if ($this->serveroutput->response[$i][$j]['name'] == "printer-uri") {
1999
                        $this->printers_uri = array_merge($this->printers_uri,array($this->serveroutput->response[$i][$j]['value']));
2000
2001
                        return;
2002
                        
2003
                        }
2004
2005
        $this->printers_uri = array_merge($this->printers_uri,array(''));
2006
 
2007
    }
2008
2009
    */
2010
2011
    // REQUEST BUILDING
2012
    protected function _stringCancel($job_uri)
2013
    {
2014
    
2015
        if (!isset($this->setup->charset))
2016
        {
2017
            self::setCharset();
2018
        }
2019
        if (!isset($this->setup->datatype))
2020
        {
2021
            self::setBinary();
2022
        }
2023
        if (!isset($this->setup->language))
2024
        {
2025
            self::setLanguage('en_us');
2026
        }
2027
        if (!$this->requesting_user)   
2028
        {
2029
            self::setUserName();
2030
        }
2031
        if (!isset($this->meta->message))
2032
        {
2033
            $this->meta->message = '';
2034
        }
2035
2036
        self::_setOperationId();
2037
2038
        self::_setJobUri($job_uri);
2039
2040
        if (!isset($this->error_generation->request_body_malformed))
2041
        {
2042
            $this->error_generation->request_body_malformed = "";
2043
        }
2044
2045
        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
2046
                         . chr(0x00) . chr(0x08) // cancel-Job | operation-id
2047
                         . $this->meta->operation_id //           request-id
2048
                         . $this->error_generation->request_body_malformed
2049
                         . chr(0x01) // start operation-attributes | operation-attributes-tag
2050
                         . $this->meta->charset
2051
                         . $this->meta->language
2052
                         . $this->meta->job_uri
2053
                         . $this->meta->username
2054
                         . $this->meta->message
2055
                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
2056
                         
2057
        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
2058
        return TRUE;
2059
    }
2060
}
2061