Completed
Branch develop (35ba9e)
by
unknown
21:24
created
htdocs/includes/restler/framework/Luracast/Restler/EventDispatcher.php 1 patch
Indentation   +71 added lines, -71 removed lines patch added patch discarded remove patch
@@ -15,84 +15,84 @@
 block discarded – undo
15 15
 
16 16
 class EventDispatcher
17 17
 {
18
-    private $listeners = array();
19
-    protected static $_waitList = array();
18
+	private $listeners = array();
19
+	protected static $_waitList = array();
20 20
 
21
-    public static $self;
22
-    protected $events = array();
21
+	public static $self;
22
+	protected $events = array();
23 23
 
24
-    public function __construct() {
25
-        static::$self = $this;
26
-        if (!empty(static::$_waitList)) {
27
-            foreach (static::$_waitList as $param) {
28
-                call_user_func_array(array($this,$param[0]), $param[1]);
29
-            }
30
-        }
31
-    }
24
+	public function __construct() {
25
+		static::$self = $this;
26
+		if (!empty(static::$_waitList)) {
27
+			foreach (static::$_waitList as $param) {
28
+				call_user_func_array(array($this,$param[0]), $param[1]);
29
+			}
30
+		}
31
+	}
32 32
 
33
-    public static function __callStatic($eventName, $params)
34
-    {
35
-        if (0 === strpos($eventName, 'on')) {
36
-            if(static::$self){
37
-                return call_user_func_array(array(static::$self, $eventName), $params);
38
-            }
39
-            static::$_waitList[] = func_get_args();
40
-            return false;
41
-        }
42
-    }
33
+	public static function __callStatic($eventName, $params)
34
+	{
35
+		if (0 === strpos($eventName, 'on')) {
36
+			if(static::$self){
37
+				return call_user_func_array(array(static::$self, $eventName), $params);
38
+			}
39
+			static::$_waitList[] = func_get_args();
40
+			return false;
41
+		}
42
+	}
43 43
 
44
-    public function __call($eventName, $params)
45
-    {
46
-        if (0 === strpos($eventName, 'on')) {
47
-            if (!isset($this->listeners[$eventName]) || !is_array($this->listeners[$eventName]))
48
-                $this->listeners[$eventName] = array();
49
-            $this->listeners[$eventName][] = $params[0];
50
-        }
51
-        return $this;
52
-    }
44
+	public function __call($eventName, $params)
45
+	{
46
+		if (0 === strpos($eventName, 'on')) {
47
+			if (!isset($this->listeners[$eventName]) || !is_array($this->listeners[$eventName]))
48
+				$this->listeners[$eventName] = array();
49
+			$this->listeners[$eventName][] = $params[0];
50
+		}
51
+		return $this;
52
+	}
53 53
 
54
-    public static function addListener($eventName, Closure $callback)
55
-    {
56
-        return static::$eventName($callback);
57
-    }
54
+	public static function addListener($eventName, Closure $callback)
55
+	{
56
+		return static::$eventName($callback);
57
+	}
58 58
 
59
-    public function on(array $eventHandlers)
60
-    {
61
-        for (
62
-            $count = count($eventHandlers),
63
-                $events = array_map(
64
-                    'ucfirst',
65
-                    $keys = array_keys(
66
-                        $eventHandlers = array_change_key_case(
67
-                            $eventHandlers,
68
-                            CASE_LOWER
69
-                        )
70
-                    )
71
-                ),
72
-                $i = 0;
73
-            $i < $count;
74
-            call_user_func(
75
-                array($this, "on{$events[$i]}"),
76
-                $eventHandlers[$keys[$i++]]
77
-            )
78
-        );
79
-    }
59
+	public function on(array $eventHandlers)
60
+	{
61
+		for (
62
+			$count = count($eventHandlers),
63
+				$events = array_map(
64
+					'ucfirst',
65
+					$keys = array_keys(
66
+						$eventHandlers = array_change_key_case(
67
+							$eventHandlers,
68
+							CASE_LOWER
69
+						)
70
+					)
71
+				),
72
+				$i = 0;
73
+			$i < $count;
74
+			call_user_func(
75
+				array($this, "on{$events[$i]}"),
76
+				$eventHandlers[$keys[$i++]]
77
+			)
78
+		);
79
+	}
80 80
 
81
-    /**
82
-     * Fire an event to notify all listeners
83
-     *
84
-     * @param string $eventName name of the event
85
-     * @param array  $params    event related data
86
-     */
87
-    protected function dispatch($eventName, array $params = array())
88
-    {
89
-        $this->events[] = $eventName;
90
-        $params = func_get_args();
91
-        $eventName = 'on'.ucfirst(array_shift($params));
92
-        if (isset($this->listeners[$eventName]))
93
-            foreach ($this->listeners[$eventName] as $callback)
94
-                call_user_func_array($callback, $params);
95
-    }
81
+	/**
82
+	 * Fire an event to notify all listeners
83
+	 *
84
+	 * @param string $eventName name of the event
85
+	 * @param array  $params    event related data
86
+	 */
87
+	protected function dispatch($eventName, array $params = array())
88
+	{
89
+		$this->events[] = $eventName;
90
+		$params = func_get_args();
91
+		$eventName = 'on'.ucfirst(array_shift($params));
92
+		if (isset($this->listeners[$eventName]))
93
+			foreach ($this->listeners[$eventName] as $callback)
94
+				call_user_func_array($callback, $params);
95
+	}
96 96
 
97 97
 }
98 98
 
Please login to merge, or discard this patch.
htdocs/includes/restler/framework/Luracast/Restler/ExplorerInfo.php 1 patch
Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -8,16 +8,16 @@
 block discarded – undo
8 8
  */
9 9
 class ExplorerInfo
10 10
 {
11
-    public static $title = 'Restler API Explorer';
12
-    public static $description = 'Live API Documentation';
13
-    public static $termsOfService = null;
14
-    public static $contact = array(
15
-        'name'  => 'Restler Support',
16
-        'url'   => 'luracast.com/products/restler',
17
-        'email' => '[email protected]',
18
-    );
19
-    public static $license = array(
20
-        'name' => 'LGPL-2.1',
21
-        'url'  => 'https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html',
22
-    );
11
+	public static $title = 'Restler API Explorer';
12
+	public static $description = 'Live API Documentation';
13
+	public static $termsOfService = null;
14
+	public static $contact = array(
15
+		'name'  => 'Restler Support',
16
+		'url'   => 'luracast.com/products/restler',
17
+		'email' => '[email protected]',
18
+	);
19
+	public static $license = array(
20
+		'name' => 'LGPL-2.1',
21
+		'url'  => 'https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html',
22
+	);
23 23
 }
24 24
\ No newline at end of file
Please login to merge, or discard this patch.
htdocs/includes/printipp/CupsPrintIPP.php 1 patch
Indentation   +721 added lines, -721 removed lines patch added patch discarded remove patch
@@ -40,735 +40,735 @@
 block discarded – undo
40 40
 
41 41
 class CupsPrintIPP extends ExtendedPrintIPP
42 42
 {
43
-    public $printers_attributes;
44
-    public $defaults_attributes;
43
+	public $printers_attributes;
44
+	public $defaults_attributes;
45 45
 
46
-    protected $parsed;
47
-    protected $output;
46
+	protected $parsed;
47
+	protected $output;
48 48
 
49
-    public function __construct()
50
-    {
51
-        parent::__construct();
52
-        self::_initTags();
53
-    }
49
+	public function __construct()
50
+	{
51
+		parent::__construct();
52
+		self::_initTags();
53
+	}
54 54
 
55 55
 //
56 56
 // OPERATIONS
57 57
 //
58
-    public function cupsGetDefaults($attributes=array("all"))
59
-    {
60
-        //The CUPS-Get-Default operation returns the default printer URI and attributes
61
-
62
-        $this->jobs = array_merge($this->jobs,array(""));
63
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
64
-        $this->parsed = array();
65
-        unset($this->printer_attributes);
66
-
67
-        if (!isset($this->setup->charset))
68
-        {
69
-            self::setCharset();
70
-        }
71
-
72
-        if (!isset($this->setup->language))
73
-        {
74
-            self::setLanguage('en');
75
-        }
76
-
77
-        self::_setOperationId();
78
-
79
-        for($i = 0 ; $i < count($attributes) ; $i++)
80
-        {
81
-            if ($i == 0)
82
-            {
83
-                $this->meta->attributes = chr(0x44) // Keyword
84
-                                        . self::_giveMeStringLength('requested-attributes')
85
-                                        . 'requested-attributes'
86
-                                        . self::_giveMeStringLength($attributes[0])
87
-                                        . $attributes[0];
88
-            }
89
-            else
90
-            {
91
-                $this->meta->attributes .= chr(0x44) // Keyword
92
-                                        .  chr(0x0).chr(0x0) // zero-length name
93
-                                        .  self::_giveMeStringLength($attributes[$i])
94
-                                        .  $attributes[$i];
95
-            }
96
-        }
97
-
98
-        $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
99
-                         . chr(0x40). chr(0x01) // operation:  cups vendor extension: get defaults
100
-                         . $this->meta->operation_id // request-id
101
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
102
-                         . $this->meta->charset
103
-                         . $this->meta->language
104
-                         . $this->meta->attributes
105
-                         . chr(0x03); // end operations attribute
106
-
107
-        $this->output = $this->stringjob;
108
-
109
-        self::_putDebug("Request: ".$this->output);
110
-
111
-        $post_values = array( "Content-Type" => "application/ipp",
112
-                              "Data" => $this->output);
113
-
114
-        if (self::_sendHttp ($post_values,'/'))
115
-        {
116
-
117
-            if(self::_parseServerOutput())
118
-            {
119
-                self::_parsePrinterAttributes();
120
-            }
121
-        }
122
-
123
-       $this->attributes = &$this->printer_attributes;
124
-
125
-       if (isset($this->printer_attributes->printer_type))
126
-       {
127
-                    $printer_type = $this->printer_attributes->printer_type->_value0;
128
-                    $table = self::_interpretPrinterType($printer_type);
129
-
130
-                    for($i = 0 ; $i < count($table) ; $i++ )
131
-                    {
132
-                        $index = '_value'.$i;
133
-                        $this->printer_attributes->printer_type->$index = $table[$i];
134
-                        }
135
-                    }
136
-
137
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
138
-        {
139
-
140
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
141
-            if ($this->serveroutput->status == "successfull-ok")
142
-            {
143
-                self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
144
-            }
145
-            else
146
-            {
147
-                self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
148
-            }
149
-
150
-            return $this->serveroutput->status;
151
-        }
152
-        else
153
-        {
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
-
161
-    public function cupsAcceptJobs($printer_uri)
162
-    {
163
-    //The CUPS-Get-Default operation returns the default printer URI and attributes
164
-
165
-        $this->jobs = array_merge($this->jobs,array(""));
166
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
167
-        $this->parsed = array();
168
-        unset($this->printer_attributes);
169
-
170
-        if (!isset($this->setup->charset))
171
-        {
172
-            self::setCharset();
173
-        }
174
-
175
-        if (!isset($this->setup->language))
176
-        {
177
-            self::setLanguage('en');
178
-        }
179
-
180
-        self::_setOperationId();
181
-
182
-        $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
183
-                         . chr(0x40). chr(0x08) // operation:  cups vendor extension: Accept-Jobs
184
-                         . $this->meta->operation_id // request-id
185
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
186
-                         . $this->meta->charset
187
-                         . $this->meta->language
188
-                         . chr(0x45) // uri
189
-                         . self::_giveMeStringLength('printer-uri')
190
-                         . 'printer-uri'
191
-                         . self::_giveMeStringLength($printer_uri)
192
-                         . $printer_uri
193
-                         . chr(0x03); // end operations attribute
194
-
195
-        $this->output = $this->stringjob;
196
-
197
-        self::_putDebug("Request: ".$this->output);
198
-
199
-        $post_values = array( "Content-Type" => "application/ipp",
200
-                              "Data" => $this->output);
201
-
202
-        if (self::_sendHttp ($post_values,'/admin/'))
203
-        {
204
-
205
-            if(self::_parseServerOutput())
206
-            {
207
-                self::_parseAttributes();
208
-            }
209
-        }
210
-
211
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
212
-        {
213
-
214
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
215
-            if ($this->serveroutput->status == "successfull-ok")
216
-            {
217
-                self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
218
-            }
219
-            else
220
-            {
221
-                self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
222
-            }
223
-
224
-            return $this->serveroutput->status;
225
-        }
226
-        else
227
-        {
228
-            $this->status = array_merge($this->status,array("OPERATION FAILED"));
229
-            self::_errorLog("getting defaults : OPERATION FAILED",1);
230
-            }
231
-    return false;
232
-    }
233
-
234
-
235
-    public function cupsRejectJobs($printer_uri,$printer_state_message)
236
-    {
237
-    //The CUPS-Get-Default operation returns the default printer URI and attributes
238
-
239
-        $this->jobs = array_merge($this->jobs,array(""));
240
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
241
-        $this->parsed = array();
242
-        unset($this->attributes);
243
-
244
-        if (!isset($this->setup->charset))
245
-        {
246
-            self::setCharset();
247
-        }
248
-
249
-        if (!isset($this->setup->language))
250
-        {
251
-            self::setLanguage('en');
252
-        }
253
-
254
-        self::_setOperationId();
255
-
256
-        $message = "";
257
-        if ($printer_state_message)
258
-        {
259
-            $message = chr(0x04) // start printer-attributes
260
-                     . chr(0x41) // textWithoutLanguage
261
-                     . self::_giveMeStringLength("printer-state-message")
262
-                     . "printer-state-message"
263
-                     . self::_giveMeStringLength($printer_state_message)
264
-                     . $printer_state_message;
265
-        }
266
-
267
-       $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
268
-                         . chr(0x40). chr(0x09) // operation:  cups vendor extension: Reject-Jobs
269
-                         . $this->meta->operation_id // request-id
270
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
271
-                         . $this->meta->charset
272
-                         . $this->meta->language
273
-                         . chr(0x45) // uri
274
-                         . self::_giveMeStringLength('printer-uri')
275
-                         . 'printer-uri'
276
-                         . self::_giveMeStringLength($printer_uri)
277
-                         . $printer_uri
278
-                         . $message
279
-                         . chr(0x03); // end operations attribute
280
-
281
-        $this->output = $this->stringjob;
282
-
283
-        self::_putDebug("Request: ".$this->output);
284
-
285
-        $post_values = array( "Content-Type" => "application/ipp",
286
-                              "Data" => $this->output);
287
-
288
-        if (self::_sendHttp ($post_values,'/admin/'))
289
-        {
290
-
291
-            if(self::_parseServerOutput())
292
-            {
293
-                self::_parseAttributes();
294
-            }
295
-        }
296
-
297
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
298
-        {
299
-
300
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
301
-            if ($this->serveroutput->status == "successfull-ok")
302
-            {
303
-                self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
304
-            }
305
-            else
306
-            {
307
-                self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
308
-            }
309
-
310
-            return $this->serveroutput->status;
311
-        }
312
-        else
313
-        {
314
-            $this->status = array_merge($this->status,array("OPERATION FAILED"));
315
-            self::_errorLog("getting defaults : OPERATION FAILED",1);
316
-        }
317
-        return false;
318
-    }
319
-
320
-
321
-    public function getPrinters($printer_location=false,$printer_info=false,$attributes=array())
322
-    {
323
-        if (count($attributes) == 0)
324
-        {
325
-            true;
326
-        }
327
-        $attributes=array('printer-uri-supported', 'printer-location', 'printer-info', 'printer-type', 'color-supported', 'printer-name');
328
-        $this->jobs = array_merge($this->jobs,array(""));
329
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
330
-
331
-        unset ($this->printers_attributes);
332
-
333
-        if (!isset($this->setup->charset))
334
-        {
335
-            self::setCharset();
336
-        }
337
-
338
-        if (!isset($this->setup->language))
339
-        {
340
-            self::setLanguage('en-us');
341
-        }
342
-
343
-        self::_setOperationId();
344
-
345
-        $this->meta->attributes='';
346
-
347
-        if ($printer_location)
348
-        {
349
-            $this->meta->attributes .= chr(0x41) // textWithoutLanguage
350
-                                    . self::_giveMeStringLength('printer-location')
351
-                                    . 'printer-location'
352
-                                    . self::_giveMeStringLength($printer_location)
353
-                                    . $printer_location;
354
-        }
355
-
356
-        if ($printer_info)
357
-        {
358
-            $this->meta->attributes .= chr(0x41) // textWithoutLanguage
359
-                                    . self::_giveMeStringLength('printer-info')
360
-                                    . 'printer-info'
361
-                                    . self::_giveMeStringLength($printer_info)
362
-                                    . $printer_info;
363
-        }
364
-
365
-        for($i = 0 ; $i < count($attributes) ; $i++)
366
-        {
367
-            if ($i == 0)
368
-            {
369
-                $this->meta->attributes .= chr(0x44) // Keyword
370
-                                        . self::_giveMeStringLength('requested-attributes')
371
-                                        . 'requested-attributes'
372
-                                        . self::_giveMeStringLength($attributes[0])
373
-                                        . $attributes[0];
374
-            }
375
-            else
376
-            {
377
-                $this->meta->attributes .= chr(0x44) // Keyword
378
-                                        .  chr(0x0).chr(0x0) // zero-length name
379
-                                        .  self::_giveMeStringLength($attributes[$i])
380
-                                        .  $attributes[$i];
381
-            }
382
-        }
383
-
384
-        $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
385
-                         . chr(0x40). chr(0x02) // operation:  cups vendor extension: get printers
386
-                         . $this->meta->operation_id //           request-id
387
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
388
-                         . $this->meta->charset
389
-                         . $this->meta->language
390
-                         . $this->meta->attributes
391
-                         . chr(0x03); // end operations attribute
392
-
393
-        $this->output = $this->stringjob;
394
-
395
-        $post_values = array( "Content-Type" => "application/ipp",
396
-                              "Data" => $this->output);
397
-
398
-        if (self::_sendHttp ($post_values,'/'))
399
-        {
400
-
401
-            if(self::_parseServerOutput())
402
-            {
403
-                $this->_getAvailablePrinters();
404
-            }
405
-        }
406
-
407
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
408
-        {
409
-
410
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
411
-            if ($this->serveroutput->status == "successfull-ok")
412
-            {
413
-                self::_errorLog("getting printers: ".$this->serveroutput->status,3);
414
-            }
415
-            else
416
-            {
417
-                self::_errorLog("getting printers: ".$this->serveroutput->status,1);
418
-            }
419
-            return $this->serveroutput->status;
420
-        }
421
-        else
422
-        {
423
-            $this->status = array_merge($this->status,array("OPERATION FAILED"));
424
-            self::_errorLog("getting printers : OPERATION FAILED",1);
425
-        }
426
-        return false;
427
-    }
428
-
429
-
430
-    public function cupsGetPrinters ()
431
-    {
432
-        // alias for getPrinters();
433
-        self::getPrinters();
434
-    }
435
-
436
-
437
-    public function getPrinterAttributes()
438
-    {
439
-        // complete informations from parent with Cups-specific stuff
440
-
441
-        if(!$result = parent::getPrinterAttributes())
442
-        {
443
-            return FALSE;
444
-        }
445
-        if(!isset($this->printer_attributes))
446
-        {
447
-            return FALSE;
448
-        }
449
-
450
-        if (isset ($this->printer_attributes->printer_type))
451
-        {
452
-            $printer_type = $this->printer_attributes->printer_type->_value0;
453
-            $table = self::_interpretPrinterType($printer_type);
454
-
455
-            for($i = 0 ; $i < count($table) ; $i++ )
456
-            {
457
-                $index = '_value'.$i;
458
-                $this->printer_attributes->printer_type->$index = $table[$i];
459
-            }
460
-        }
461
-
462
-        return $result;
463
-    }
58
+	public function cupsGetDefaults($attributes=array("all"))
59
+	{
60
+		//The CUPS-Get-Default operation returns the default printer URI and attributes
61
+
62
+		$this->jobs = array_merge($this->jobs,array(""));
63
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
64
+		$this->parsed = array();
65
+		unset($this->printer_attributes);
66
+
67
+		if (!isset($this->setup->charset))
68
+		{
69
+			self::setCharset();
70
+		}
71
+
72
+		if (!isset($this->setup->language))
73
+		{
74
+			self::setLanguage('en');
75
+		}
76
+
77
+		self::_setOperationId();
78
+
79
+		for($i = 0 ; $i < count($attributes) ; $i++)
80
+		{
81
+			if ($i == 0)
82
+			{
83
+				$this->meta->attributes = chr(0x44) // Keyword
84
+										. self::_giveMeStringLength('requested-attributes')
85
+										. 'requested-attributes'
86
+										. self::_giveMeStringLength($attributes[0])
87
+										. $attributes[0];
88
+			}
89
+			else
90
+			{
91
+				$this->meta->attributes .= chr(0x44) // Keyword
92
+										.  chr(0x0).chr(0x0) // zero-length name
93
+										.  self::_giveMeStringLength($attributes[$i])
94
+										.  $attributes[$i];
95
+			}
96
+		}
97
+
98
+		$this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
99
+						 . chr(0x40). chr(0x01) // operation:  cups vendor extension: get defaults
100
+						 . $this->meta->operation_id // request-id
101
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
102
+						 . $this->meta->charset
103
+						 . $this->meta->language
104
+						 . $this->meta->attributes
105
+						 . chr(0x03); // end operations attribute
106
+
107
+		$this->output = $this->stringjob;
108
+
109
+		self::_putDebug("Request: ".$this->output);
110
+
111
+		$post_values = array( "Content-Type" => "application/ipp",
112
+							  "Data" => $this->output);
113
+
114
+		if (self::_sendHttp ($post_values,'/'))
115
+		{
116
+
117
+			if(self::_parseServerOutput())
118
+			{
119
+				self::_parsePrinterAttributes();
120
+			}
121
+		}
122
+
123
+	   $this->attributes = &$this->printer_attributes;
124
+
125
+	   if (isset($this->printer_attributes->printer_type))
126
+	   {
127
+					$printer_type = $this->printer_attributes->printer_type->_value0;
128
+					$table = self::_interpretPrinterType($printer_type);
129
+
130
+					for($i = 0 ; $i < count($table) ; $i++ )
131
+					{
132
+						$index = '_value'.$i;
133
+						$this->printer_attributes->printer_type->$index = $table[$i];
134
+						}
135
+					}
136
+
137
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
138
+		{
139
+
140
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
141
+			if ($this->serveroutput->status == "successfull-ok")
142
+			{
143
+				self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
144
+			}
145
+			else
146
+			{
147
+				self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
148
+			}
149
+
150
+			return $this->serveroutput->status;
151
+		}
152
+		else
153
+		{
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
+
161
+	public function cupsAcceptJobs($printer_uri)
162
+	{
163
+	//The CUPS-Get-Default operation returns the default printer URI and attributes
164
+
165
+		$this->jobs = array_merge($this->jobs,array(""));
166
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
167
+		$this->parsed = array();
168
+		unset($this->printer_attributes);
169
+
170
+		if (!isset($this->setup->charset))
171
+		{
172
+			self::setCharset();
173
+		}
174
+
175
+		if (!isset($this->setup->language))
176
+		{
177
+			self::setLanguage('en');
178
+		}
179
+
180
+		self::_setOperationId();
181
+
182
+		$this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
183
+						 . chr(0x40). chr(0x08) // operation:  cups vendor extension: Accept-Jobs
184
+						 . $this->meta->operation_id // request-id
185
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
186
+						 . $this->meta->charset
187
+						 . $this->meta->language
188
+						 . chr(0x45) // uri
189
+						 . self::_giveMeStringLength('printer-uri')
190
+						 . 'printer-uri'
191
+						 . self::_giveMeStringLength($printer_uri)
192
+						 . $printer_uri
193
+						 . chr(0x03); // end operations attribute
194
+
195
+		$this->output = $this->stringjob;
196
+
197
+		self::_putDebug("Request: ".$this->output);
198
+
199
+		$post_values = array( "Content-Type" => "application/ipp",
200
+							  "Data" => $this->output);
201
+
202
+		if (self::_sendHttp ($post_values,'/admin/'))
203
+		{
204
+
205
+			if(self::_parseServerOutput())
206
+			{
207
+				self::_parseAttributes();
208
+			}
209
+		}
210
+
211
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
212
+		{
213
+
214
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
215
+			if ($this->serveroutput->status == "successfull-ok")
216
+			{
217
+				self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
218
+			}
219
+			else
220
+			{
221
+				self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
222
+			}
223
+
224
+			return $this->serveroutput->status;
225
+		}
226
+		else
227
+		{
228
+			$this->status = array_merge($this->status,array("OPERATION FAILED"));
229
+			self::_errorLog("getting defaults : OPERATION FAILED",1);
230
+			}
231
+	return false;
232
+	}
233
+
234
+
235
+	public function cupsRejectJobs($printer_uri,$printer_state_message)
236
+	{
237
+	//The CUPS-Get-Default operation returns the default printer URI and attributes
238
+
239
+		$this->jobs = array_merge($this->jobs,array(""));
240
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
241
+		$this->parsed = array();
242
+		unset($this->attributes);
243
+
244
+		if (!isset($this->setup->charset))
245
+		{
246
+			self::setCharset();
247
+		}
248
+
249
+		if (!isset($this->setup->language))
250
+		{
251
+			self::setLanguage('en');
252
+		}
253
+
254
+		self::_setOperationId();
255
+
256
+		$message = "";
257
+		if ($printer_state_message)
258
+		{
259
+			$message = chr(0x04) // start printer-attributes
260
+					 . chr(0x41) // textWithoutLanguage
261
+					 . self::_giveMeStringLength("printer-state-message")
262
+					 . "printer-state-message"
263
+					 . self::_giveMeStringLength($printer_state_message)
264
+					 . $printer_state_message;
265
+		}
266
+
267
+	   $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
268
+						 . chr(0x40). chr(0x09) // operation:  cups vendor extension: Reject-Jobs
269
+						 . $this->meta->operation_id // request-id
270
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
271
+						 . $this->meta->charset
272
+						 . $this->meta->language
273
+						 . chr(0x45) // uri
274
+						 . self::_giveMeStringLength('printer-uri')
275
+						 . 'printer-uri'
276
+						 . self::_giveMeStringLength($printer_uri)
277
+						 . $printer_uri
278
+						 . $message
279
+						 . chr(0x03); // end operations attribute
280
+
281
+		$this->output = $this->stringjob;
282
+
283
+		self::_putDebug("Request: ".$this->output);
284
+
285
+		$post_values = array( "Content-Type" => "application/ipp",
286
+							  "Data" => $this->output);
287
+
288
+		if (self::_sendHttp ($post_values,'/admin/'))
289
+		{
290
+
291
+			if(self::_parseServerOutput())
292
+			{
293
+				self::_parseAttributes();
294
+			}
295
+		}
296
+
297
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
298
+		{
299
+
300
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
301
+			if ($this->serveroutput->status == "successfull-ok")
302
+			{
303
+				self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
304
+			}
305
+			else
306
+			{
307
+				self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
308
+			}
309
+
310
+			return $this->serveroutput->status;
311
+		}
312
+		else
313
+		{
314
+			$this->status = array_merge($this->status,array("OPERATION FAILED"));
315
+			self::_errorLog("getting defaults : OPERATION FAILED",1);
316
+		}
317
+		return false;
318
+	}
319
+
320
+
321
+	public function getPrinters($printer_location=false,$printer_info=false,$attributes=array())
322
+	{
323
+		if (count($attributes) == 0)
324
+		{
325
+			true;
326
+		}
327
+		$attributes=array('printer-uri-supported', 'printer-location', 'printer-info', 'printer-type', 'color-supported', 'printer-name');
328
+		$this->jobs = array_merge($this->jobs,array(""));
329
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
330
+
331
+		unset ($this->printers_attributes);
332
+
333
+		if (!isset($this->setup->charset))
334
+		{
335
+			self::setCharset();
336
+		}
337
+
338
+		if (!isset($this->setup->language))
339
+		{
340
+			self::setLanguage('en-us');
341
+		}
342
+
343
+		self::_setOperationId();
344
+
345
+		$this->meta->attributes='';
346
+
347
+		if ($printer_location)
348
+		{
349
+			$this->meta->attributes .= chr(0x41) // textWithoutLanguage
350
+									. self::_giveMeStringLength('printer-location')
351
+									. 'printer-location'
352
+									. self::_giveMeStringLength($printer_location)
353
+									. $printer_location;
354
+		}
355
+
356
+		if ($printer_info)
357
+		{
358
+			$this->meta->attributes .= chr(0x41) // textWithoutLanguage
359
+									. self::_giveMeStringLength('printer-info')
360
+									. 'printer-info'
361
+									. self::_giveMeStringLength($printer_info)
362
+									. $printer_info;
363
+		}
364
+
365
+		for($i = 0 ; $i < count($attributes) ; $i++)
366
+		{
367
+			if ($i == 0)
368
+			{
369
+				$this->meta->attributes .= chr(0x44) // Keyword
370
+										. self::_giveMeStringLength('requested-attributes')
371
+										. 'requested-attributes'
372
+										. self::_giveMeStringLength($attributes[0])
373
+										. $attributes[0];
374
+			}
375
+			else
376
+			{
377
+				$this->meta->attributes .= chr(0x44) // Keyword
378
+										.  chr(0x0).chr(0x0) // zero-length name
379
+										.  self::_giveMeStringLength($attributes[$i])
380
+										.  $attributes[$i];
381
+			}
382
+		}
383
+
384
+		$this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
385
+						 . chr(0x40). chr(0x02) // operation:  cups vendor extension: get printers
386
+						 . $this->meta->operation_id //           request-id
387
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
388
+						 . $this->meta->charset
389
+						 . $this->meta->language
390
+						 . $this->meta->attributes
391
+						 . chr(0x03); // end operations attribute
392
+
393
+		$this->output = $this->stringjob;
394
+
395
+		$post_values = array( "Content-Type" => "application/ipp",
396
+							  "Data" => $this->output);
397
+
398
+		if (self::_sendHttp ($post_values,'/'))
399
+		{
400
+
401
+			if(self::_parseServerOutput())
402
+			{
403
+				$this->_getAvailablePrinters();
404
+			}
405
+		}
406
+
407
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
408
+		{
409
+
410
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
411
+			if ($this->serveroutput->status == "successfull-ok")
412
+			{
413
+				self::_errorLog("getting printers: ".$this->serveroutput->status,3);
414
+			}
415
+			else
416
+			{
417
+				self::_errorLog("getting printers: ".$this->serveroutput->status,1);
418
+			}
419
+			return $this->serveroutput->status;
420
+		}
421
+		else
422
+		{
423
+			$this->status = array_merge($this->status,array("OPERATION FAILED"));
424
+			self::_errorLog("getting printers : OPERATION FAILED",1);
425
+		}
426
+		return false;
427
+	}
428
+
429
+
430
+	public function cupsGetPrinters ()
431
+	{
432
+		// alias for getPrinters();
433
+		self::getPrinters();
434
+	}
435
+
436
+
437
+	public function getPrinterAttributes()
438
+	{
439
+		// complete informations from parent with Cups-specific stuff
440
+
441
+		if(!$result = parent::getPrinterAttributes())
442
+		{
443
+			return FALSE;
444
+		}
445
+		if(!isset($this->printer_attributes))
446
+		{
447
+			return FALSE;
448
+		}
449
+
450
+		if (isset ($this->printer_attributes->printer_type))
451
+		{
452
+			$printer_type = $this->printer_attributes->printer_type->_value0;
453
+			$table = self::_interpretPrinterType($printer_type);
454
+
455
+			for($i = 0 ; $i < count($table) ; $i++ )
456
+			{
457
+				$index = '_value'.$i;
458
+				$this->printer_attributes->printer_type->$index = $table[$i];
459
+			}
460
+		}
461
+
462
+		return $result;
463
+	}
464 464
 
465 465
 //
466 466
 // SETUP
467 467
 //
468
-    protected function _initTags ()
469
-    {
470
-        // override parent with specific cups attributes
471
-
472
-        $operation_tags = array ();
473
-        $this->operation_tags = array_merge ($this->operation_tags, $operation_tags);
474
-
475
-        $job_tags = array ( "job-billing" => array("tag" => "textWithoutLanguage"),
476
-                            "blackplot" => array("tag" => "boolean"),
477
-                            "brightness" => array("tag" => "integer"),
478
-                            "columns" => array("tag" => "integer"),
479
-                            "cpi" => array("tag" => "enum"),
480
-                            "fitplot" => array("tag" => "boolean"),
481
-                            "gamma" => array("tag" => "integer"),
482
-                            "hue" => array("tag" => "integer"),
483
-                            "lpi" => array("tag" => "enum"),
484
-                            "mirror" => array("tag","boolean"),
485
-                            "natural-scaling" => array("tag" => "integer"),
486
-                            "number-up-layout" => array("tag" => "keyword"),
487
-                            "page-border" => array("tag" => "keyword"),
488
-                            "page-bottom" => array("tag" => "integer"),
489
-                            "page-label" => array("tag" => "textWithoutLanguage"),
490
-                            "page-left" => array("tag" => "integer"),
491
-                            "page-right" => array("tag" => "integer"),
492
-                            "page-set" => array("tag" => "keyword"),
493
-                            "page-top" => array("tag" => "integer"),
494
-                            "penwidth" => array("tag" => "integer"),
495
-                            "position" => array("tag" => "keyword"),
496
-                            "ppi" => array("tag" => "integer"),
497
-                            "prettyprint" => array("tag","boolean"),
498
-                            "saturation" => array("tag" => "integer"),
499
-                            "scaling" => array("tag" => "integer"),
500
-                            "wrap" => array("tag","boolean"),
501
-
502
-                            );
503
-        $this->job_tags = array_merge ($this->job_tags, $job_tags);
504
-    }
505
-
506
-    //
507
-    // REQUEST BUILDING
508
-    //
509
-    protected function _enumBuild ($tag,$value)
510
-    {
511
-        $value_built = parent::_enumBuild($tag,$value);
512
-
513
-        switch ($tag)
514
-        {
515
-           case "cpi":
516
-                switch ($value)
517
-                {
518
-                    case '10':
519
-                        $value_built = chr(10);
520
-                        break;
521
-                    case '12':
522
-                        $value_built = chr(12);
523
-                        break;
524
-                    case '17':
525
-                        $value_built = chr(17);
526
-                        break;
527
-                    default:
528
-                        $value_built = chr(10);
529
-                }
530
-            break;
531
-            case "lpi":
532
-                switch ($value)
533
-                {
534
-                    case '6':
535
-                        $value_built = chr(6);
536
-                        break;
537
-                    case '8':
538
-                        $value_built = chr(8);
539
-                        break;
540
-                    default:
541
-                        $value_built = chr(6);
542
-                }
543
-            break;
544
-            }
545
-
546
-        $prepend = '';
547
-        while ((strlen($value_built) + strlen($prepend)) < 4)
548
-            $prepend .= chr(0);
549
-        return $prepend.$value_built;
550
-    }
551
-
552
-    //
553
-    // RESPONSE PARSING
554
-    //
555
-    private function _getAvailablePrinters ()
556
-    {
557
-        $this->available_printers = array();
558
-        $this->printer_map = array();
559
-        $k = 0;
560
-        $this->printers_attributes = new \stdClass();
561
-
562
-        for ($i = 0 ; (array_key_exists($i,$this->serveroutput->response)) ; $i ++)
563
-        {
564
-            if (($this->serveroutput->response[$i]['attributes']) == "printer-attributes")
565
-            {
566
-                $phpname = "_printer".$k;
567
-                $this->printers_attributes->$phpname = new \stdClass();
568
-                for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
569
-                {
570
-
571
-                    $value = $this->serveroutput->response[$i][$j]['value'];
572
-                    $name = str_replace("-","_",$this->serveroutput->response[$i][$j]['name']);
573
-
574
-                    switch ($name)
575
-                    {
576
-                        case "printer_uri_supported":
577
-                            $this->available_printers = array_merge($this->available_printers,array($value));
578
-                            break;
579
-                        case "printer_type":
580
-                            $table = self::_interpretPrinterType($value);
581
-                            $this->printers_attributes->$phpname->$name = new \stdClass();
582
-
583
-                            for($l = 0 ; $l < count($table) ; $l++ )
584
-                            {
585
-                                $index = '_value'.$l;
586
-                                $this->printers_attributes->$phpname->$name->$index = $table[$l];
587
-                            }
588
-
589
-                            break;
590
-                        case '':
591
-                            break;
592
-                        case 'printer_name':
593
-                            $this->printer_map[$value] = $k;
594
-                            break;
595
-                        default:
596
-                            $this->printers_attributes->$phpname->$name = $value;
597
-                            break;
598
-                    }
599
-                }
600
-                $k ++;
601
-            }
602
-        }
603
-    }
604
-
605
-    protected function _getEnumVendorExtensions ($value_parsed)
606
-    {
607
-        switch ($value_parsed)
608
-        {
609
-            case 0x4002:
610
-                $value = 'Get-Availables-Printers';
611
-                break;
612
-            default:
613
-                $value = sprintf('Unknown(Cups extension for operations): 0x%x',$value_parsed);
614
-                break;
615
-        }
616
-
617
-        if (isset($value))
618
-        {
619
-            return ($value);
620
-        }
621
-
622
-        return sprintf('Unknown: 0x%x',$value_parsed);
623
-    }
624
-
625
-
626
-    private function _interpretPrinterType($value)
627
-    {
628
-        $value_parsed = 0;
629
-        for ($i = strlen($value) ; $i > 0 ; $i --)
630
-        {
631
-            $value_parsed += pow(256,($i - 1)) * ord($value[strlen($value) - $i]);
632
-        }
633
-
634
-        $type[0] = $type[1] = $type[2] = $type[3] = $type[4] = $type[5] = '';
635
-        $type[6] = $type[7] = $type[8] = $type[9] = $type[10] = '';
636
-        $type[11] = $type[12] = $type[13] = $type[14] = $type[15] = '';
637
-        $type[16] = $type[17] = $type[18] = $type[19] = '';
638
-
639
-        if ($value_parsed %2 == 1)
640
-        {
641
-            $type[0] = 'printer-class';
642
-            $value_parsed -= 1;
643
-        }
644
-
645
-        if ($value_parsed %4 == 2 )
646
-        {
647
-            $type[1] = 'remote-destination';
648
-            $value_parsed -= 2;
649
-        }
650
-
651
-        if ($value_parsed %8 == 4 )
652
-        {
653
-            $type[2] = 'print-black';
654
-            $value_parsed -= 4;
655
-        }
656
-
657
-        if ($value_parsed %16 == 8 )
658
-        {
659
-            $type[3] = 'print-color';
660
-            $value_parsed -= 8;
661
-        }
662
-
663
-        if ($value_parsed %32 == 16)
664
-        {
665
-            $type[4] = 'hardware-print-on-both-sides';
666
-            $value_parsed -= 16;
667
-        }
668
-
669
-        if ($value_parsed %64 == 32)
670
-        {
671
-            $type[5] = 'hardware-staple-output';
672
-            $value_parsed -= 32;
673
-        }
674
-
675
-        if ($value_parsed %128 == 64)
676
-        {
677
-            $type[6] = 'hardware-fast-copies';
678
-            $value_parsed -= 64;
679
-        }
680
-
681
-        if ($value_parsed %256 == 128)
682
-        {
683
-            $type[7] = 'hardware-fast-copy-collation';
684
-            $value_parsed -= 128;
685
-        }
686
-
687
-        if ($value_parsed %512 == 256)
688
-        {
689
-            $type[8] = 'punch-output';
690
-            $value_parsed -= 256;
691
-        }
692
-
693
-        if ($value_parsed %1024 == 512)
694
-        {
695
-            $type[9] = 'cover-output';
696
-            $value_parsed -= 512;
697
-        }
698
-
699
-        if ($value_parsed %2048 == 1024)
700
-        {
701
-            $type[10] = 'bind-output';
702
-            $value_parsed -= 1024;
703
-        }
704
-
705
-        if ($value_parsed %4096 == 2048)
706
-        {
707
-            $type[11] = 'sort-output';
708
-            $value_parsed -= 2048;
709
-        }
710
-
711
-        if ($value_parsed %8192 == 4096)
712
-        {
713
-            $type[12] = 'handle-media-up-to-US-Legal-A4';
714
-            $value_parsed -= 4096;
715
-        }
716
-
717
-        if ($value_parsed %16384 == 8192)
718
-        {
719
-            $type[13] = 'handle-media-between-US-Legal-A4-and-ISO_C-A2';
720
-            $value_parsed -= 8192;
721
-        }
722
-
723
-        if ($value_parsed %32768 == 16384)
724
-        {
725
-            $type[14] = 'handle-media-larger-than-ISO_C-A2';
726
-            $value_parsed -= 16384;
727
-        }
728
-
729
-        if ($value_parsed %65536 == 32768)
730
-        {
731
-            $type[15] = 'handle-user-defined-media-sizes';
732
-            $value_parsed -= 32768;
733
-        }
734
-
735
-        if ($value_parsed %131072 == 65536)
736
-        {
737
-            $type[16] = 'implicit-server-generated-class';
738
-            $value_parsed -= 65536;
739
-        }
740
-
741
-        if ($value_parsed %262144 == 131072)
742
-        {
743
-            $type[17] = 'network-default-printer';
744
-            $value_parsed -= 131072;
745
-        }
746
-
747
-        if ($value_parsed %524288 == 262144)
748
-        {
749
-            $type[18] = 'fax-device';
750
-            $value_parsed -= 262144;
751
-        }
752
-
753
-        return $type;
754
-    }
755
-
756
-
757
-    protected function _interpretEnum($attribute_name,$value)
758
-    {
759
-        $value_parsed = self::_interpretInteger($value);
760
-
761
-        switch ($attribute_name)
762
-        {
763
-            case 'cpi':
764
-            case 'lpi':
765
-                $value = $value_parsed;
766
-                break;
767
-            default:
768
-                $value = parent::_interpretEnum($attribute_name,$value);
769
-                break;
770
-        }
771
-
772
-        return $value;
773
-    }
468
+	protected function _initTags ()
469
+	{
470
+		// override parent with specific cups attributes
471
+
472
+		$operation_tags = array ();
473
+		$this->operation_tags = array_merge ($this->operation_tags, $operation_tags);
474
+
475
+		$job_tags = array ( "job-billing" => array("tag" => "textWithoutLanguage"),
476
+							"blackplot" => array("tag" => "boolean"),
477
+							"brightness" => array("tag" => "integer"),
478
+							"columns" => array("tag" => "integer"),
479
+							"cpi" => array("tag" => "enum"),
480
+							"fitplot" => array("tag" => "boolean"),
481
+							"gamma" => array("tag" => "integer"),
482
+							"hue" => array("tag" => "integer"),
483
+							"lpi" => array("tag" => "enum"),
484
+							"mirror" => array("tag","boolean"),
485
+							"natural-scaling" => array("tag" => "integer"),
486
+							"number-up-layout" => array("tag" => "keyword"),
487
+							"page-border" => array("tag" => "keyword"),
488
+							"page-bottom" => array("tag" => "integer"),
489
+							"page-label" => array("tag" => "textWithoutLanguage"),
490
+							"page-left" => array("tag" => "integer"),
491
+							"page-right" => array("tag" => "integer"),
492
+							"page-set" => array("tag" => "keyword"),
493
+							"page-top" => array("tag" => "integer"),
494
+							"penwidth" => array("tag" => "integer"),
495
+							"position" => array("tag" => "keyword"),
496
+							"ppi" => array("tag" => "integer"),
497
+							"prettyprint" => array("tag","boolean"),
498
+							"saturation" => array("tag" => "integer"),
499
+							"scaling" => array("tag" => "integer"),
500
+							"wrap" => array("tag","boolean"),
501
+
502
+							);
503
+		$this->job_tags = array_merge ($this->job_tags, $job_tags);
504
+	}
505
+
506
+	//
507
+	// REQUEST BUILDING
508
+	//
509
+	protected function _enumBuild ($tag,$value)
510
+	{
511
+		$value_built = parent::_enumBuild($tag,$value);
512
+
513
+		switch ($tag)
514
+		{
515
+		   case "cpi":
516
+				switch ($value)
517
+				{
518
+					case '10':
519
+						$value_built = chr(10);
520
+						break;
521
+					case '12':
522
+						$value_built = chr(12);
523
+						break;
524
+					case '17':
525
+						$value_built = chr(17);
526
+						break;
527
+					default:
528
+						$value_built = chr(10);
529
+				}
530
+			break;
531
+			case "lpi":
532
+				switch ($value)
533
+				{
534
+					case '6':
535
+						$value_built = chr(6);
536
+						break;
537
+					case '8':
538
+						$value_built = chr(8);
539
+						break;
540
+					default:
541
+						$value_built = chr(6);
542
+				}
543
+			break;
544
+			}
545
+
546
+		$prepend = '';
547
+		while ((strlen($value_built) + strlen($prepend)) < 4)
548
+			$prepend .= chr(0);
549
+		return $prepend.$value_built;
550
+	}
551
+
552
+	//
553
+	// RESPONSE PARSING
554
+	//
555
+	private function _getAvailablePrinters ()
556
+	{
557
+		$this->available_printers = array();
558
+		$this->printer_map = array();
559
+		$k = 0;
560
+		$this->printers_attributes = new \stdClass();
561
+
562
+		for ($i = 0 ; (array_key_exists($i,$this->serveroutput->response)) ; $i ++)
563
+		{
564
+			if (($this->serveroutput->response[$i]['attributes']) == "printer-attributes")
565
+			{
566
+				$phpname = "_printer".$k;
567
+				$this->printers_attributes->$phpname = new \stdClass();
568
+				for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
569
+				{
570
+
571
+					$value = $this->serveroutput->response[$i][$j]['value'];
572
+					$name = str_replace("-","_",$this->serveroutput->response[$i][$j]['name']);
573
+
574
+					switch ($name)
575
+					{
576
+						case "printer_uri_supported":
577
+							$this->available_printers = array_merge($this->available_printers,array($value));
578
+							break;
579
+						case "printer_type":
580
+							$table = self::_interpretPrinterType($value);
581
+							$this->printers_attributes->$phpname->$name = new \stdClass();
582
+
583
+							for($l = 0 ; $l < count($table) ; $l++ )
584
+							{
585
+								$index = '_value'.$l;
586
+								$this->printers_attributes->$phpname->$name->$index = $table[$l];
587
+							}
588
+
589
+							break;
590
+						case '':
591
+							break;
592
+						case 'printer_name':
593
+							$this->printer_map[$value] = $k;
594
+							break;
595
+						default:
596
+							$this->printers_attributes->$phpname->$name = $value;
597
+							break;
598
+					}
599
+				}
600
+				$k ++;
601
+			}
602
+		}
603
+	}
604
+
605
+	protected function _getEnumVendorExtensions ($value_parsed)
606
+	{
607
+		switch ($value_parsed)
608
+		{
609
+			case 0x4002:
610
+				$value = 'Get-Availables-Printers';
611
+				break;
612
+			default:
613
+				$value = sprintf('Unknown(Cups extension for operations): 0x%x',$value_parsed);
614
+				break;
615
+		}
616
+
617
+		if (isset($value))
618
+		{
619
+			return ($value);
620
+		}
621
+
622
+		return sprintf('Unknown: 0x%x',$value_parsed);
623
+	}
624
+
625
+
626
+	private function _interpretPrinterType($value)
627
+	{
628
+		$value_parsed = 0;
629
+		for ($i = strlen($value) ; $i > 0 ; $i --)
630
+		{
631
+			$value_parsed += pow(256,($i - 1)) * ord($value[strlen($value) - $i]);
632
+		}
633
+
634
+		$type[0] = $type[1] = $type[2] = $type[3] = $type[4] = $type[5] = '';
635
+		$type[6] = $type[7] = $type[8] = $type[9] = $type[10] = '';
636
+		$type[11] = $type[12] = $type[13] = $type[14] = $type[15] = '';
637
+		$type[16] = $type[17] = $type[18] = $type[19] = '';
638
+
639
+		if ($value_parsed %2 == 1)
640
+		{
641
+			$type[0] = 'printer-class';
642
+			$value_parsed -= 1;
643
+		}
644
+
645
+		if ($value_parsed %4 == 2 )
646
+		{
647
+			$type[1] = 'remote-destination';
648
+			$value_parsed -= 2;
649
+		}
650
+
651
+		if ($value_parsed %8 == 4 )
652
+		{
653
+			$type[2] = 'print-black';
654
+			$value_parsed -= 4;
655
+		}
656
+
657
+		if ($value_parsed %16 == 8 )
658
+		{
659
+			$type[3] = 'print-color';
660
+			$value_parsed -= 8;
661
+		}
662
+
663
+		if ($value_parsed %32 == 16)
664
+		{
665
+			$type[4] = 'hardware-print-on-both-sides';
666
+			$value_parsed -= 16;
667
+		}
668
+
669
+		if ($value_parsed %64 == 32)
670
+		{
671
+			$type[5] = 'hardware-staple-output';
672
+			$value_parsed -= 32;
673
+		}
674
+
675
+		if ($value_parsed %128 == 64)
676
+		{
677
+			$type[6] = 'hardware-fast-copies';
678
+			$value_parsed -= 64;
679
+		}
680
+
681
+		if ($value_parsed %256 == 128)
682
+		{
683
+			$type[7] = 'hardware-fast-copy-collation';
684
+			$value_parsed -= 128;
685
+		}
686
+
687
+		if ($value_parsed %512 == 256)
688
+		{
689
+			$type[8] = 'punch-output';
690
+			$value_parsed -= 256;
691
+		}
692
+
693
+		if ($value_parsed %1024 == 512)
694
+		{
695
+			$type[9] = 'cover-output';
696
+			$value_parsed -= 512;
697
+		}
698
+
699
+		if ($value_parsed %2048 == 1024)
700
+		{
701
+			$type[10] = 'bind-output';
702
+			$value_parsed -= 1024;
703
+		}
704
+
705
+		if ($value_parsed %4096 == 2048)
706
+		{
707
+			$type[11] = 'sort-output';
708
+			$value_parsed -= 2048;
709
+		}
710
+
711
+		if ($value_parsed %8192 == 4096)
712
+		{
713
+			$type[12] = 'handle-media-up-to-US-Legal-A4';
714
+			$value_parsed -= 4096;
715
+		}
716
+
717
+		if ($value_parsed %16384 == 8192)
718
+		{
719
+			$type[13] = 'handle-media-between-US-Legal-A4-and-ISO_C-A2';
720
+			$value_parsed -= 8192;
721
+		}
722
+
723
+		if ($value_parsed %32768 == 16384)
724
+		{
725
+			$type[14] = 'handle-media-larger-than-ISO_C-A2';
726
+			$value_parsed -= 16384;
727
+		}
728
+
729
+		if ($value_parsed %65536 == 32768)
730
+		{
731
+			$type[15] = 'handle-user-defined-media-sizes';
732
+			$value_parsed -= 32768;
733
+		}
734
+
735
+		if ($value_parsed %131072 == 65536)
736
+		{
737
+			$type[16] = 'implicit-server-generated-class';
738
+			$value_parsed -= 65536;
739
+		}
740
+
741
+		if ($value_parsed %262144 == 131072)
742
+		{
743
+			$type[17] = 'network-default-printer';
744
+			$value_parsed -= 131072;
745
+		}
746
+
747
+		if ($value_parsed %524288 == 262144)
748
+		{
749
+			$type[18] = 'fax-device';
750
+			$value_parsed -= 262144;
751
+		}
752
+
753
+		return $type;
754
+	}
755
+
756
+
757
+	protected function _interpretEnum($attribute_name,$value)
758
+	{
759
+		$value_parsed = self::_interpretInteger($value);
760
+
761
+		switch ($attribute_name)
762
+		{
763
+			case 'cpi':
764
+			case 'lpi':
765
+				$value = $value_parsed;
766
+				break;
767
+			default:
768
+				$value = parent::_interpretEnum($attribute_name,$value);
769
+				break;
770
+		}
771
+
772
+		return $value;
773
+	}
774 774
 }
775 775
\ No newline at end of file
Please login to merge, or discard this patch.
htdocs/includes/printipp/PrintIPP.php 1 patch
Indentation   +1976 added lines, -1976 removed lines patch added patch discarded remove patch
@@ -44,1944 +44,1944 @@  discard block
 block discarded – undo
44 44
 
45 45
 class PrintIPP extends BasicIPP
46 46
 {
47
-    public function __construct()
48
-    {
49
-        parent::__construct();
50
-    }
47
+	public function __construct()
48
+	{
49
+		parent::__construct();
50
+	}
51 51
 
52 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;
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 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("job status: %s",
126
-                    $this->serveroutput->status));
127
-                }
128
-            }
129
-            return $this->serveroutput->status; 
130
-        }
131
-
132
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
133
-        $this->jobs = array_merge($this->jobs,array(""));
134
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
135
-        self::_errorLog("printing job : OPERATION FAILED",1);
136
-
137
-        return false;
138
-    }
139
-
140
-    public function cancelJob ($job_uri)
141
-    {
142
-        $this->jobs = array_merge($this->jobs,array(""));
143
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
144
-
145
-        self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
146
-
147
-        if (!$this->_stringCancel($job_uri))
148
-        {
149
-            return FALSE;
150
-        }
151
-
152
-        self::_putDebug( _("Cancelling Job $job_uri\n"),3); 
153
-
154
-        $this->output = $this->stringjob;
155
-
156
-        $post_values = array( "Content-Type"=>"application/ipp",
157
-                              "Data"=>$this->output);
158
-
159
-        if (self::_sendHttp ($post_values,$this->paths['jobs']))
160
-        {
161
-            self::_parseServerOutput();
162
-        }
163
-
164
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
165
-        {
166
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
167
-
168
-            if ($this->serveroutput->status == "successfull-ok")
169
-            {
170
-                self::_errorLog("cancelling job $job_uri: ".$this->serveroutput->status,3);
171
-            }
172
-            else
173
-            {
174
-                self::_errorLog("cancelling job $job_uri: ".$this->serveroutput->status,1);
175
-            }
176
-            return $this->serveroutput->status; 
177
-        }
178
-
179
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
180
-        self::_errorLog("cancelling job : OPERATION FAILED",3);
181
-
182
-        return false;
183
-    }
184
-
185
-    public function validateJob ()
186
-    {
187
-        $this->jobs = array_merge($this->jobs,array(""));
188
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
189
-
190
-        $this->serveroutput->response = '';
191
-
192
-        self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
193
-
194
-        self::_putDebug( _("Validate Job\n"),2); 
195
-
196
-        if (!isset($this->setup->charset))
197
-        {
198
-            self::setCharset();
199
-        }
200
-        if (!isset($this->setup->datatype))
201
-        {
202
-            self::setBinary();
203
-        }
204
-
205
-        if (!isset($this->setup->uri))
206
-        {
207
-            $this->getPrinters();
208
-            unset($this->jobs[count($this->jobs) - 1]);
209
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
210
-            unset($this->status[count($this->status) - 1]);
211
-
212
-            if (array_key_exists(0,$this->available_printers))
213
-            {
214
-               self::setPrinterURI($this->available_printers[0]);
215
-            }
216
-            else
217
-            {
218
-                trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
219
-                self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
220
-                self::_errorLog(" Printer URI is not set, die",2);
221
-                return FALSE;
222
-                }
223
-            }
224
-
225
-        if (!isset($this->meta->copies))
226
-        {
227
-            self::setCopies(1);
228
-        }
229
-
230
-        if (!isset($this->setup->copies))
231
-        {
232
-            self::setCopies(1);
233
-        }
234
-
235
-        if (!isset($this->setup->language))
236
-        {
237
-            self::setLanguage('en_us');
238
-        }
239
-
240
-        if (!isset($this->setup->mime_media_type))
241
-        {
242
-            self::setMimeMediaType();
243
-        }
244
-
245
-        if ($this->setup->datatype != "TEXT")
246
-        {
247
-            unset ($this->setup->mime_media_type);
248
-        }
249
-
250
-        if (!isset($this->setup->jobname))
251
-        {
252
-            if (is_readable($this->data))
253
-            {
254
-                self::setJobName(basename($this->data),true);
255
-            }
256
-            else
257
-            {
258
-                self::setJobName();
259
-            }
260
-        }
261
-        unset($this->setup->jobname);
262
-
263
-        if (!isset($this->meta->username))
264
-        {
265
-            self::setUserName();
266
-        }
267
-
268
-        if (!isset($this->meta->fidelity))
269
-        {
270
-            $this->meta->fidelity = '';
271
-        }
272
-
273
-        if (!isset($this->meta->document_name))
274
-        {
275
-            $this->meta->document_name = '';
276
-        }
277
-
278
-        if (!isset($this->meta->sides))
279
-        {
280
-            $this->meta->sides = '';
281
-        }
282
-
283
-        if (!isset($this->meta->page_ranges))
284
-        {
285
-            $this->meta->page_ranges = '';
286
-        }
287
-
288
-        $jobattributes = '';
289
-        $operationattributes = '';
290
-        $printerattributes = '';
291
-        self::_buildValues ($operationattributes,$jobattributes,$printerattributes);
292
-
293
-        self::_setOperationId();
294
-
295
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
296
-                         . chr(0x00) . chr (0x04) // Validate-Job | operation-id
297
-                         . $this->meta->operation_id //           request-id
298
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
299
-                         . $this->meta->charset
300
-                         . $this->meta->language
301
-                         . $this->meta->printer_uri
302
-                         . $this->meta->username
303
-                         . $this->meta->jobname
304
-                         . $this->meta->fidelity
305
-                         . $this->meta->document_name
306
-                         . $this->meta->mime_media_type
307
-                         . $operationattributes
308
-                         . chr(0x02) // start job-attributes | job-attributes-tag
309
-                         . $this->meta->copies
310
-                         . $this->meta->sides
311
-                         . $this->meta->page_ranges
312
-                         . $jobattributes
313
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
314
-
315
-        self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
316
-
317
-        $this->output = $this->stringjob;
318
-
319
-        $post_values = array( "Content-Type"=>"application/ipp",
320
-                              "Data"=>$this->output);
321
-
322
-        if (self::_sendHttp ($post_values,$this->paths['printers']))
323
-        {
324
-            if(self::_parseServerOutput())
325
-            {
326
-                self::_parseAttributes();
327
-            }
328
-        }
329
-
330
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
331
-        {
332
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
333
-
334
-            if ($this->serveroutput->status == "successfull-ok")
335
-            {
336
-                self::_errorLog("validate job: ".$this->serveroutput->status,3);
337
-            }
338
-            else
339
-            {
340
-                self::_errorLog("validate job: ".$this->serveroutput->status,1);
341
-            }
342
-            return $this->serveroutput->status; 
343
-        }
344
-
345
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
346
-        self::_errorLog("validate job : OPERATION FAILED",3);
347
-
348
-        return false;
349
-    }
350
-
351
-    public function getPrinterAttributes()
352
-    {
353
-        $this->jobs = array_merge($this->jobs,array(""));
354
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
355
-
356
-        $jobattributes = '';
357
-        $operationattributes = '';
358
-        self::_buildValues($operationattributes,$jobattributes,$printerattributes);
359
-        self::_setOperationId();
360
-        $this->parsed = array();
361
-        unset($this->printer_attributes);
362
-
363
-        if (!isset($this->setup->uri))
364
-        {
365
-            $this->getPrinters();
366
-            unset($this->jobs[count($this->jobs) - 1]);
367
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
368
-            unset($this->status[count($this->status) - 1]);
369
-
370
-            if (array_key_exists(0,$this->available_printers))
371
-            {
372
-               self::setPrinterURI($this->available_printers[0]);
373
-            }
374
-            else
375
-            {
376
-                trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
377
-                self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
378
-                self::_errorLog(" Printer URI is not set, die",2);
379
-                return FALSE;
380
-                }
381
-            }
382
-
383
-        if (!isset($this->setup->charset))
384
-        {
385
-            self::setCharset();
386
-        }
387
-
388
-        if (!isset($this->setup->language))
389
-        {
390
-            self::setLanguage('en_us');
391
-        }
392
-
393
-        if (!isset($this->meta->username))
394
-        {
395
-            self::setUserName();
396
-        }
397
-
398
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
399
-                         . chr(0x00) . chr (0x0b) // Print-URI | operation-id
400
-                         . $this->meta->operation_id //           request-id
401
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
402
-                         . $this->meta->charset
403
-                         . $this->meta->language
404
-                         . $this->meta->printer_uri
405
-                         . $this->meta->username
406
-                         . $printerattributes
407
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
408
-
409
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
410
-
411
-        self::_putDebug(sprintf(_("Getting printer attributes of %s\n"),$this->printer_uri),2); 
412
-
413
-        $this->output = $this->stringjob;
414
-
415
-        $post_values = array( "Content-Type"=>"application/ipp",
416
-                              "Data"=>$this->output);
417
-
418
-        if (self::_sendHttp ($post_values,$this->paths['root']))
419
-        {
420
-            if (self::_parseServerOutput())
421
-            {
422
-                self::_parsePrinterAttributes(); 
423
-            }
424
-        }
425
-
426
-        $this->attributes = &$this->printer_attributes;
427
-
428
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
429
-        {
430
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
431
-
432
-            if  ($this->serveroutput->status == "successfull-ok")
433
-            {
434
-                self::_errorLog(sprintf(_("getting printer attributes of %s: %s"),$this->printer_uri,
435
-                                                                        $this->serveroutput->status),3);
436
-            }
437
-            else 
438
-            {
439
-                self::_errorLog(sprintf(_("getting printer attributes of %s: %s"),$this->printer_uri,
440
-                                                                        $this->serveroutput->status),1);
441
-            }
442
-
443
-            return $this->serveroutput->status;
444
-        }
445
-
446
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
447
-        self::_errorLog(date("Y-m-d H:i:s : ")
448
-            .basename($_SERVER['PHP_SELF'])
449
-            .sprintf(_("getting printer's attributes of %s : OPERATION FAILED"),
450
-                $this->printer_uri),3);
451
-
452
-        return false;
453
-    }
454
-
455
-    public function getJobs($my_jobs=true,$limit=0,$which_jobs="not-completed",$subset=false)
456
-    {
457
-        $this->jobs = array_merge($this->jobs,array(""));
458
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
459
-
460
-        self::_setOperationId();
461
-        $this->parsed = array();
462
-        unset($this->printer_attributes);
463
-
464
-        if (!isset($this->setup->uri))
465
-        {
466
-            $this->getPrinters();
467
-            unset($this->jobs[count($this->jobs) - 1]);
468
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
469
-            unset($this->status[count($this->status) - 1]);
470
-
471
-            if (array_key_exists(0,$this->available_printers))
472
-            {
473
-               self::setPrinterURI($this->available_printers[0]);
474
-            }
475
-            else
476
-            {
477
-                trigger_error(_("getJobs: Printer URI is not set: die"),E_USER_WARNING);
478
-                self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
479
-                self::_errorLog("getJobs: Printer URI is not set, die",2);
480
-                return FALSE;
481
-                }
482
-            }
483
-
484
-        if (!isset($this->setup->charset))
485
-        {
486
-            self::setCharset();
487
-        }
488
-
489
-        if (!isset($this->setup->language))
490
-        {
491
-            self::setLanguage('en_us');
492
-        }
493
-
494
-        if (!isset($this->meta->username))
495
-        {
496
-            self::setUserName();
497
-        }
498
-
499
-        if ($limit)
500
-        {
501
-            $limit = self::_integerBuild($limit);
502
-            $this->meta->limit = chr(0x21) // integer
503
-                               . self::_giveMeStringLength('limit')
504
-                               . 'limit'
505
-                               . self::_giveMeStringLength($limit)
506
-                               . $limit;
507
-        }
508
-        else
509
-        {
510
-            $this->meta->limit = '';
511
-        }
512
-
513
-        if ($which_jobs == 'completed')
514
-        {
515
-                $this->meta->which_jobs = chr(0x44) // keyword
516
-                                        . self::_giveMeStringLength('which-jobs')
517
-                                        . 'which-jobs'
518
-                                        . self::_giveMeStringLength($which_jobs)
519
-                                        . $which_jobs;
520
-        }
521
-        else
522
-        {
523
-            $this->meta->which_jobs = "";
524
-        }
525
-
526
-        if ($my_jobs)
527
-        {
528
-            $this->meta->my_jobs = chr(0x22) // boolean
529
-                                 . self::_giveMeStringLength('my-jobs')
530
-                                 . 'my-jobs'
531
-                                 . self::_giveMeStringLength(chr(0x01))
532
-                                 . chr(0x01);
533
-        }
534
-        else
535
-        {
536
-            $this->meta->my_jobs = '';
537
-        }
538
-
539
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
540
-                         . chr(0x00) . chr (0x0A) // Get-Jobs | operation-id
541
-                         . $this->meta->operation_id //           request-id
542
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
543
-                         . $this->meta->charset
544
-                         . $this->meta->language
545
-                         . $this->meta->printer_uri
546
-                         . $this->meta->username
547
-                         . $this->meta->limit
548
-                         . $this->meta->which_jobs 
549
-                         . $this->meta->my_jobs;
550
-       if ($subset)
551
-       {
552
-           $this->stringjob .=
553
-                          chr(0x44) // keyword
554
-                         . self::_giveMeStringLength('requested-attributes')
555
-                         . 'requested-attributes'
556
-                         . self::_giveMeStringLength('job-uri')
557
-                         . 'job-uri'
558
-                         . chr(0x44) // keyword
559
-                         . self::_giveMeStringLength('')
560
-                         . ''
561
-                         . self::_giveMeStringLength('job-name')
562
-                         . 'job-name'
563
-                         . chr(0x44) // keyword
564
-                         . self::_giveMeStringLength('')
565
-                         . ''
566
-                         . self::_giveMeStringLength('job-state')
567
-                         . 'job-state'
568
-                         . chr(0x44) // keyword
569
-                         . self::_giveMeStringLength('')
570
-                         . ''
571
-                         . self::_giveMeStringLength('job-state-reason')
572
-                         . 'job-state-reason';
573
-        }
574
-        else
575
-        { # cups 1.4.4 doesn't return much of anything without this
576
-            $this->stringjob .=
577
-                          chr(0x44) // keyword
578
-                         . self::_giveMeStringLength('requested-attributes')
579
-                         . 'requested-attributes'
580
-                         . self::_giveMeStringLength('all')
581
-                         . 'all';
582
-        }
583
-        $this->stringjob .= chr(0x03); // end-of-attributes | end-of-attributes-tag
584
-
585
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
586
-
587
-        self::_putDebug(sprintf(_("getting jobs of %s\n"),$this->printer_uri),2); 
588
-
589
-        $this->output = $this->stringjob;
590
-
591
-        $post_values = array( "Content-Type"=>"application/ipp",
592
-                              "Data"=>$this->output);
593
-
594
-        if (self::_sendHttp ($post_values,$this->paths['jobs']))
595
-        {
596
-            if (self::_parseServerOutput())
597
-            {
598
-                self::_parseJobsAttributes();
599
-            }
600
-        }
601
-
602
-        $this->attributes = &$this->jobs_attributes;
603
-
604
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
605
-        {
606
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
607
-
608
-            if ($this->serveroutput->status == "successfull-ok")
609
-            {
610
-                self::_errorLog(sprintf(_("getting jobs of printer %s: "),$this->printer_uri)
611
-                            .$this->serveroutput->status,3);
612
-            }
613
-            else
614
-            {
615
-                 self::_errorLog(sprintf(_("getting jobs of printer %s: "),$this->printer_uri)
616
-                                             .$this->serveroutput->status,1);
617
-            }
618
-
619
-            return $this->serveroutput->status;
620
-        }
621
-
622
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
623
-        self::_errorLog(date("Y-m-d H:i:s : ")
624
-                        .basename($_SERVER['PHP_SELF'])
625
-                        .sprintf(_("getting jobs of %s : OPERATION FAILED"),
626
-                                     $this->printer_uri),3);
627
-
628
-    return false;
629
-    }
630
-
631
-
632
-    public function getJobAttributes($job_uri,$subset=false,$attributes_group="all")
633
-    {
634
-        $this->jobs = array_merge($this->jobs,array(""));
635
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
636
-
637
-        if (!$job_uri)
638
-        {
639
-            trigger_error(_("getJobAttributes: Job URI is not set, die."));
640
-            return FALSE;
641
-            }
642
-
643
-        self::_setOperationId();
644
-        $this->parsed = array();
645
-        unset($this->printer_attributes);
646
-
647
-        if (!isset($this->setup->uri))
648
-        {
649
-            $this->getPrinters();
650
-            unset($this->jobs[count($this->jobs) - 1]);
651
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
652
-            unset($this->status[count($this->status) - 1]);
653
-
654
-            if (array_key_exists(0,$this->available_printers))
655
-            {
656
-               self::setPrinterURI($this->available_printers[0]);
657
-            }
658
-            else
659
-            {
660
-                trigger_error(_("getJobs: Printer URI is not set: die"),E_USER_WARNING);
661
-                self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
662
-                self::_errorLog("getJobs: Printer URI is not set, die",2);
663
-                return FALSE;
664
-            }
665
-        }
666
-
667
-        if (!isset($this->setup->charset))
668
-        {
669
-            self::setCharset();
670
-        }
671
-
672
-        if (!isset($this->setup->language))
673
-        {
674
-            self::setLanguage('en_us');
675
-        }
676
-
677
-        if (!isset($this->meta->username))
678
-        {
679
-            self::setUserName();
680
-        }
681
-
682
-        $this->meta->job_uri = chr(0x45) // URI
683
-                             . self::_giveMeStringLength('job-uri')
684
-                             . 'job-uri'
685
-                             . self::_giveMeStringLength($job_uri)
686
-                             . $job_uri;
687
-
688
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
689
-                         . chr(0x00) . chr (0x09) // Get-Job-Attributes | operation-id
690
-                         . $this->meta->operation_id //           request-id
691
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
692
-                         . $this->meta->charset
693
-                         . $this->meta->language
694
-                         . $this->meta->job_uri
695
-                         . $this->meta->username;
696
-        if ($subset)
697
-        {
698
-            $this->stringjob .=
699
-                          chr(0x44) // keyword
700
-                         . self::_giveMeStringLength('requested-attributes')
701
-                         . 'requested-attributes'
702
-                         . self::_giveMeStringLength('job-uri')
703
-                         . 'job-uri'
704
-                         . chr(0x44) // keyword
705
-                         . self::_giveMeStringLength('')
706
-                         . ''
707
-                         . self::_giveMeStringLength('job-name')
708
-                         . 'job-name'
709
-                         . chr(0x44) // keyword
710
-                         . self::_giveMeStringLength('')
711
-                         . ''
712
-                         . self::_giveMeStringLength('job-state')
713
-                         . 'job-state'
714
-                         . chr(0x44) // keyword
715
-                         . self::_giveMeStringLength('')
716
-                         . ''
717
-                         . self::_giveMeStringLength('job-state-reason')
718
-                         . 'job-state-reason';
719
-        }
720
-        elseif($attributes_group)
721
-        {
722
-            switch($attributes_group)
723
-            {
724
-                case 'job-template':
725
-                    break;
726
-                case 'job-description':
727
-                    break;
728
-                case 'all':
729
-                    break;
730
-                default:
731
-                    trigger_error(_('not a valid attribute group: ').$attributes_group,E_USER_NOTICE);
732
-                    $attributes_group = '';
733
-                    break;
734
-            }
735
-            $this->stringjob .=
736
-                          chr(0x44) // keyword
737
-                         . self::_giveMeStringLength('requested-attributes')
738
-                         . 'requested-attributes'
739
-                         . self::_giveMeStringLength($attributes_group)
740
-                         . $attributes_group;
741
-        }
742
-        $this->stringjob .= chr(0x03); // end-of-attributes | end-of-attributes-tag
743
-
744
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
745
-
746
-        self::_putDebug(sprintf(_("getting jobs of %s\n"),$this->printer_uri),2); 
747
-
748
-        $this->output = $this->stringjob;
749
-
750
-        $post_values = array( "Content-Type"=>"application/ipp",
751
-                              "Data"=>$this->output);
752
-
753
-        if (self::_sendHttp ($post_values,$this->paths['jobs']))
754
-        {
755
-            if (self::_parseServerOutput())
756
-            {
757
-                self::_parseJobAttributes();
758
-            }
759
-        }
760
-
761
-        $this->attributes = &$this->job_attributes;
762
-
763
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
764
-        {
765
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
766
-
767
-            if ($this->serveroutput->status == "successfull-ok")
768
-            {
769
-                self::_errorLog(sprintf(_("getting job attributes for %s: "),$job_uri)
770
-                            .$this->serveroutput->status,3);
771
-            }
772
-            else
773
-            {
774
-                 self::_errorLog(sprintf(_("getting job attributes for %s: "),$job_uri)
775
-                                             .$this->serveroutput->status,1);
776
-            }
777
-
778
-            return $this->serveroutput->status;
779
-        }
780
-
781
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
782
-        self::_errorLog(date("Y-m-d H:i:s : ")
783
-                        .basename($_SERVER['PHP_SELF'])
784
-                        .sprintf(_("getting jobs attributes of %s : OPERATION FAILED"),
785
-                                     $job_uri),3);
786
-
787
-        return false;
788
-    }
789
-
790
-    public function getPrinters()
791
-    {
792
-        // placeholder for vendor extension operation (getAvailablePrinters for CUPS)
793
-        $this->jobs = array_merge($this->jobs,array(''));
794
-        $this->jobs_uri = array_merge($this->jobs_uri,array(''));
795
-        $this->status = array_merge($this->status,array(''));    
796
-    }
797
-
798
-    public function generateError ($error)
799
-    {
800
-        switch ($error)
801
-        {
802
-            case "request_body_malformed":
803
-                $this->error_generation->request_body_malformed = chr(0xFF);
804
-                break;
805
-            default:
806
-                true;
807
-                break;
808
-        }
809
-
810
-        trigger_error(sprintf(_('Setting Error %s'),$error),E_USER_NOTICE);
811
-    }
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("job status: %s",
126
+					$this->serveroutput->status));
127
+				}
128
+			}
129
+			return $this->serveroutput->status; 
130
+		}
131
+
132
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
133
+		$this->jobs = array_merge($this->jobs,array(""));
134
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
135
+		self::_errorLog("printing job : OPERATION FAILED",1);
136
+
137
+		return false;
138
+	}
139
+
140
+	public function cancelJob ($job_uri)
141
+	{
142
+		$this->jobs = array_merge($this->jobs,array(""));
143
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
144
+
145
+		self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
146
+
147
+		if (!$this->_stringCancel($job_uri))
148
+		{
149
+			return FALSE;
150
+		}
151
+
152
+		self::_putDebug( _("Cancelling Job $job_uri\n"),3); 
153
+
154
+		$this->output = $this->stringjob;
155
+
156
+		$post_values = array( "Content-Type"=>"application/ipp",
157
+							  "Data"=>$this->output);
158
+
159
+		if (self::_sendHttp ($post_values,$this->paths['jobs']))
160
+		{
161
+			self::_parseServerOutput();
162
+		}
163
+
164
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
165
+		{
166
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
167
+
168
+			if ($this->serveroutput->status == "successfull-ok")
169
+			{
170
+				self::_errorLog("cancelling job $job_uri: ".$this->serveroutput->status,3);
171
+			}
172
+			else
173
+			{
174
+				self::_errorLog("cancelling job $job_uri: ".$this->serveroutput->status,1);
175
+			}
176
+			return $this->serveroutput->status; 
177
+		}
178
+
179
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
180
+		self::_errorLog("cancelling job : OPERATION FAILED",3);
181
+
182
+		return false;
183
+	}
184
+
185
+	public function validateJob ()
186
+	{
187
+		$this->jobs = array_merge($this->jobs,array(""));
188
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
189
+
190
+		$this->serveroutput->response = '';
191
+
192
+		self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
193
+
194
+		self::_putDebug( _("Validate Job\n"),2); 
195
+
196
+		if (!isset($this->setup->charset))
197
+		{
198
+			self::setCharset();
199
+		}
200
+		if (!isset($this->setup->datatype))
201
+		{
202
+			self::setBinary();
203
+		}
204
+
205
+		if (!isset($this->setup->uri))
206
+		{
207
+			$this->getPrinters();
208
+			unset($this->jobs[count($this->jobs) - 1]);
209
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
210
+			unset($this->status[count($this->status) - 1]);
211
+
212
+			if (array_key_exists(0,$this->available_printers))
213
+			{
214
+			   self::setPrinterURI($this->available_printers[0]);
215
+			}
216
+			else
217
+			{
218
+				trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
219
+				self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
220
+				self::_errorLog(" Printer URI is not set, die",2);
221
+				return FALSE;
222
+				}
223
+			}
224
+
225
+		if (!isset($this->meta->copies))
226
+		{
227
+			self::setCopies(1);
228
+		}
229
+
230
+		if (!isset($this->setup->copies))
231
+		{
232
+			self::setCopies(1);
233
+		}
234
+
235
+		if (!isset($this->setup->language))
236
+		{
237
+			self::setLanguage('en_us');
238
+		}
239
+
240
+		if (!isset($this->setup->mime_media_type))
241
+		{
242
+			self::setMimeMediaType();
243
+		}
244
+
245
+		if ($this->setup->datatype != "TEXT")
246
+		{
247
+			unset ($this->setup->mime_media_type);
248
+		}
249
+
250
+		if (!isset($this->setup->jobname))
251
+		{
252
+			if (is_readable($this->data))
253
+			{
254
+				self::setJobName(basename($this->data),true);
255
+			}
256
+			else
257
+			{
258
+				self::setJobName();
259
+			}
260
+		}
261
+		unset($this->setup->jobname);
262
+
263
+		if (!isset($this->meta->username))
264
+		{
265
+			self::setUserName();
266
+		}
267
+
268
+		if (!isset($this->meta->fidelity))
269
+		{
270
+			$this->meta->fidelity = '';
271
+		}
272
+
273
+		if (!isset($this->meta->document_name))
274
+		{
275
+			$this->meta->document_name = '';
276
+		}
277
+
278
+		if (!isset($this->meta->sides))
279
+		{
280
+			$this->meta->sides = '';
281
+		}
282
+
283
+		if (!isset($this->meta->page_ranges))
284
+		{
285
+			$this->meta->page_ranges = '';
286
+		}
287
+
288
+		$jobattributes = '';
289
+		$operationattributes = '';
290
+		$printerattributes = '';
291
+		self::_buildValues ($operationattributes,$jobattributes,$printerattributes);
292
+
293
+		self::_setOperationId();
294
+
295
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
296
+						 . chr(0x00) . chr (0x04) // Validate-Job | operation-id
297
+						 . $this->meta->operation_id //           request-id
298
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
299
+						 . $this->meta->charset
300
+						 . $this->meta->language
301
+						 . $this->meta->printer_uri
302
+						 . $this->meta->username
303
+						 . $this->meta->jobname
304
+						 . $this->meta->fidelity
305
+						 . $this->meta->document_name
306
+						 . $this->meta->mime_media_type
307
+						 . $operationattributes
308
+						 . chr(0x02) // start job-attributes | job-attributes-tag
309
+						 . $this->meta->copies
310
+						 . $this->meta->sides
311
+						 . $this->meta->page_ranges
312
+						 . $jobattributes
313
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
314
+
315
+		self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
316
+
317
+		$this->output = $this->stringjob;
318
+
319
+		$post_values = array( "Content-Type"=>"application/ipp",
320
+							  "Data"=>$this->output);
321
+
322
+		if (self::_sendHttp ($post_values,$this->paths['printers']))
323
+		{
324
+			if(self::_parseServerOutput())
325
+			{
326
+				self::_parseAttributes();
327
+			}
328
+		}
329
+
330
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
331
+		{
332
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
333
+
334
+			if ($this->serveroutput->status == "successfull-ok")
335
+			{
336
+				self::_errorLog("validate job: ".$this->serveroutput->status,3);
337
+			}
338
+			else
339
+			{
340
+				self::_errorLog("validate job: ".$this->serveroutput->status,1);
341
+			}
342
+			return $this->serveroutput->status; 
343
+		}
344
+
345
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
346
+		self::_errorLog("validate job : OPERATION FAILED",3);
347
+
348
+		return false;
349
+	}
350
+
351
+	public function getPrinterAttributes()
352
+	{
353
+		$this->jobs = array_merge($this->jobs,array(""));
354
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
355
+
356
+		$jobattributes = '';
357
+		$operationattributes = '';
358
+		self::_buildValues($operationattributes,$jobattributes,$printerattributes);
359
+		self::_setOperationId();
360
+		$this->parsed = array();
361
+		unset($this->printer_attributes);
362
+
363
+		if (!isset($this->setup->uri))
364
+		{
365
+			$this->getPrinters();
366
+			unset($this->jobs[count($this->jobs) - 1]);
367
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
368
+			unset($this->status[count($this->status) - 1]);
369
+
370
+			if (array_key_exists(0,$this->available_printers))
371
+			{
372
+			   self::setPrinterURI($this->available_printers[0]);
373
+			}
374
+			else
375
+			{
376
+				trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
377
+				self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
378
+				self::_errorLog(" Printer URI is not set, die",2);
379
+				return FALSE;
380
+				}
381
+			}
382
+
383
+		if (!isset($this->setup->charset))
384
+		{
385
+			self::setCharset();
386
+		}
387
+
388
+		if (!isset($this->setup->language))
389
+		{
390
+			self::setLanguage('en_us');
391
+		}
392
+
393
+		if (!isset($this->meta->username))
394
+		{
395
+			self::setUserName();
396
+		}
397
+
398
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
399
+						 . chr(0x00) . chr (0x0b) // Print-URI | operation-id
400
+						 . $this->meta->operation_id //           request-id
401
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
402
+						 . $this->meta->charset
403
+						 . $this->meta->language
404
+						 . $this->meta->printer_uri
405
+						 . $this->meta->username
406
+						 . $printerattributes
407
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
408
+
409
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
410
+
411
+		self::_putDebug(sprintf(_("Getting printer attributes of %s\n"),$this->printer_uri),2); 
412
+
413
+		$this->output = $this->stringjob;
414
+
415
+		$post_values = array( "Content-Type"=>"application/ipp",
416
+							  "Data"=>$this->output);
417
+
418
+		if (self::_sendHttp ($post_values,$this->paths['root']))
419
+		{
420
+			if (self::_parseServerOutput())
421
+			{
422
+				self::_parsePrinterAttributes(); 
423
+			}
424
+		}
425
+
426
+		$this->attributes = &$this->printer_attributes;
427
+
428
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
429
+		{
430
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
431
+
432
+			if  ($this->serveroutput->status == "successfull-ok")
433
+			{
434
+				self::_errorLog(sprintf(_("getting printer attributes of %s: %s"),$this->printer_uri,
435
+																		$this->serveroutput->status),3);
436
+			}
437
+			else 
438
+			{
439
+				self::_errorLog(sprintf(_("getting printer attributes of %s: %s"),$this->printer_uri,
440
+																		$this->serveroutput->status),1);
441
+			}
442
+
443
+			return $this->serveroutput->status;
444
+		}
445
+
446
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
447
+		self::_errorLog(date("Y-m-d H:i:s : ")
448
+			.basename($_SERVER['PHP_SELF'])
449
+			.sprintf(_("getting printer's attributes of %s : OPERATION FAILED"),
450
+				$this->printer_uri),3);
451
+
452
+		return false;
453
+	}
454
+
455
+	public function getJobs($my_jobs=true,$limit=0,$which_jobs="not-completed",$subset=false)
456
+	{
457
+		$this->jobs = array_merge($this->jobs,array(""));
458
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
459
+
460
+		self::_setOperationId();
461
+		$this->parsed = array();
462
+		unset($this->printer_attributes);
463
+
464
+		if (!isset($this->setup->uri))
465
+		{
466
+			$this->getPrinters();
467
+			unset($this->jobs[count($this->jobs) - 1]);
468
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
469
+			unset($this->status[count($this->status) - 1]);
470
+
471
+			if (array_key_exists(0,$this->available_printers))
472
+			{
473
+			   self::setPrinterURI($this->available_printers[0]);
474
+			}
475
+			else
476
+			{
477
+				trigger_error(_("getJobs: Printer URI is not set: die"),E_USER_WARNING);
478
+				self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
479
+				self::_errorLog("getJobs: Printer URI is not set, die",2);
480
+				return FALSE;
481
+				}
482
+			}
483
+
484
+		if (!isset($this->setup->charset))
485
+		{
486
+			self::setCharset();
487
+		}
488
+
489
+		if (!isset($this->setup->language))
490
+		{
491
+			self::setLanguage('en_us');
492
+		}
493
+
494
+		if (!isset($this->meta->username))
495
+		{
496
+			self::setUserName();
497
+		}
498
+
499
+		if ($limit)
500
+		{
501
+			$limit = self::_integerBuild($limit);
502
+			$this->meta->limit = chr(0x21) // integer
503
+							   . self::_giveMeStringLength('limit')
504
+							   . 'limit'
505
+							   . self::_giveMeStringLength($limit)
506
+							   . $limit;
507
+		}
508
+		else
509
+		{
510
+			$this->meta->limit = '';
511
+		}
512
+
513
+		if ($which_jobs == 'completed')
514
+		{
515
+				$this->meta->which_jobs = chr(0x44) // keyword
516
+										. self::_giveMeStringLength('which-jobs')
517
+										. 'which-jobs'
518
+										. self::_giveMeStringLength($which_jobs)
519
+										. $which_jobs;
520
+		}
521
+		else
522
+		{
523
+			$this->meta->which_jobs = "";
524
+		}
525
+
526
+		if ($my_jobs)
527
+		{
528
+			$this->meta->my_jobs = chr(0x22) // boolean
529
+								 . self::_giveMeStringLength('my-jobs')
530
+								 . 'my-jobs'
531
+								 . self::_giveMeStringLength(chr(0x01))
532
+								 . chr(0x01);
533
+		}
534
+		else
535
+		{
536
+			$this->meta->my_jobs = '';
537
+		}
538
+
539
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
540
+						 . chr(0x00) . chr (0x0A) // Get-Jobs | operation-id
541
+						 . $this->meta->operation_id //           request-id
542
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
543
+						 . $this->meta->charset
544
+						 . $this->meta->language
545
+						 . $this->meta->printer_uri
546
+						 . $this->meta->username
547
+						 . $this->meta->limit
548
+						 . $this->meta->which_jobs 
549
+						 . $this->meta->my_jobs;
550
+	   if ($subset)
551
+	   {
552
+		   $this->stringjob .=
553
+						  chr(0x44) // keyword
554
+						 . self::_giveMeStringLength('requested-attributes')
555
+						 . 'requested-attributes'
556
+						 . self::_giveMeStringLength('job-uri')
557
+						 . 'job-uri'
558
+						 . chr(0x44) // keyword
559
+						 . self::_giveMeStringLength('')
560
+						 . ''
561
+						 . self::_giveMeStringLength('job-name')
562
+						 . 'job-name'
563
+						 . chr(0x44) // keyword
564
+						 . self::_giveMeStringLength('')
565
+						 . ''
566
+						 . self::_giveMeStringLength('job-state')
567
+						 . 'job-state'
568
+						 . chr(0x44) // keyword
569
+						 . self::_giveMeStringLength('')
570
+						 . ''
571
+						 . self::_giveMeStringLength('job-state-reason')
572
+						 . 'job-state-reason';
573
+		}
574
+		else
575
+		{ # cups 1.4.4 doesn't return much of anything without this
576
+			$this->stringjob .=
577
+						  chr(0x44) // keyword
578
+						 . self::_giveMeStringLength('requested-attributes')
579
+						 . 'requested-attributes'
580
+						 . self::_giveMeStringLength('all')
581
+						 . 'all';
582
+		}
583
+		$this->stringjob .= chr(0x03); // end-of-attributes | end-of-attributes-tag
584
+
585
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
586
+
587
+		self::_putDebug(sprintf(_("getting jobs of %s\n"),$this->printer_uri),2); 
588
+
589
+		$this->output = $this->stringjob;
590
+
591
+		$post_values = array( "Content-Type"=>"application/ipp",
592
+							  "Data"=>$this->output);
593
+
594
+		if (self::_sendHttp ($post_values,$this->paths['jobs']))
595
+		{
596
+			if (self::_parseServerOutput())
597
+			{
598
+				self::_parseJobsAttributes();
599
+			}
600
+		}
601
+
602
+		$this->attributes = &$this->jobs_attributes;
603
+
604
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
605
+		{
606
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
607
+
608
+			if ($this->serveroutput->status == "successfull-ok")
609
+			{
610
+				self::_errorLog(sprintf(_("getting jobs of printer %s: "),$this->printer_uri)
611
+							.$this->serveroutput->status,3);
612
+			}
613
+			else
614
+			{
615
+				 self::_errorLog(sprintf(_("getting jobs of printer %s: "),$this->printer_uri)
616
+											 .$this->serveroutput->status,1);
617
+			}
618
+
619
+			return $this->serveroutput->status;
620
+		}
621
+
622
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
623
+		self::_errorLog(date("Y-m-d H:i:s : ")
624
+						.basename($_SERVER['PHP_SELF'])
625
+						.sprintf(_("getting jobs of %s : OPERATION FAILED"),
626
+									 $this->printer_uri),3);
627
+
628
+	return false;
629
+	}
630
+
631
+
632
+	public function getJobAttributes($job_uri,$subset=false,$attributes_group="all")
633
+	{
634
+		$this->jobs = array_merge($this->jobs,array(""));
635
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
636
+
637
+		if (!$job_uri)
638
+		{
639
+			trigger_error(_("getJobAttributes: Job URI is not set, die."));
640
+			return FALSE;
641
+			}
642
+
643
+		self::_setOperationId();
644
+		$this->parsed = array();
645
+		unset($this->printer_attributes);
646
+
647
+		if (!isset($this->setup->uri))
648
+		{
649
+			$this->getPrinters();
650
+			unset($this->jobs[count($this->jobs) - 1]);
651
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
652
+			unset($this->status[count($this->status) - 1]);
653
+
654
+			if (array_key_exists(0,$this->available_printers))
655
+			{
656
+			   self::setPrinterURI($this->available_printers[0]);
657
+			}
658
+			else
659
+			{
660
+				trigger_error(_("getJobs: Printer URI is not set: die"),E_USER_WARNING);
661
+				self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
662
+				self::_errorLog("getJobs: Printer URI is not set, die",2);
663
+				return FALSE;
664
+			}
665
+		}
666
+
667
+		if (!isset($this->setup->charset))
668
+		{
669
+			self::setCharset();
670
+		}
671
+
672
+		if (!isset($this->setup->language))
673
+		{
674
+			self::setLanguage('en_us');
675
+		}
676
+
677
+		if (!isset($this->meta->username))
678
+		{
679
+			self::setUserName();
680
+		}
681
+
682
+		$this->meta->job_uri = chr(0x45) // URI
683
+							 . self::_giveMeStringLength('job-uri')
684
+							 . 'job-uri'
685
+							 . self::_giveMeStringLength($job_uri)
686
+							 . $job_uri;
687
+
688
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
689
+						 . chr(0x00) . chr (0x09) // Get-Job-Attributes | operation-id
690
+						 . $this->meta->operation_id //           request-id
691
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
692
+						 . $this->meta->charset
693
+						 . $this->meta->language
694
+						 . $this->meta->job_uri
695
+						 . $this->meta->username;
696
+		if ($subset)
697
+		{
698
+			$this->stringjob .=
699
+						  chr(0x44) // keyword
700
+						 . self::_giveMeStringLength('requested-attributes')
701
+						 . 'requested-attributes'
702
+						 . self::_giveMeStringLength('job-uri')
703
+						 . 'job-uri'
704
+						 . chr(0x44) // keyword
705
+						 . self::_giveMeStringLength('')
706
+						 . ''
707
+						 . self::_giveMeStringLength('job-name')
708
+						 . 'job-name'
709
+						 . chr(0x44) // keyword
710
+						 . self::_giveMeStringLength('')
711
+						 . ''
712
+						 . self::_giveMeStringLength('job-state')
713
+						 . 'job-state'
714
+						 . chr(0x44) // keyword
715
+						 . self::_giveMeStringLength('')
716
+						 . ''
717
+						 . self::_giveMeStringLength('job-state-reason')
718
+						 . 'job-state-reason';
719
+		}
720
+		elseif($attributes_group)
721
+		{
722
+			switch($attributes_group)
723
+			{
724
+				case 'job-template':
725
+					break;
726
+				case 'job-description':
727
+					break;
728
+				case 'all':
729
+					break;
730
+				default:
731
+					trigger_error(_('not a valid attribute group: ').$attributes_group,E_USER_NOTICE);
732
+					$attributes_group = '';
733
+					break;
734
+			}
735
+			$this->stringjob .=
736
+						  chr(0x44) // keyword
737
+						 . self::_giveMeStringLength('requested-attributes')
738
+						 . 'requested-attributes'
739
+						 . self::_giveMeStringLength($attributes_group)
740
+						 . $attributes_group;
741
+		}
742
+		$this->stringjob .= chr(0x03); // end-of-attributes | end-of-attributes-tag
743
+
744
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
745
+
746
+		self::_putDebug(sprintf(_("getting jobs of %s\n"),$this->printer_uri),2); 
747
+
748
+		$this->output = $this->stringjob;
749
+
750
+		$post_values = array( "Content-Type"=>"application/ipp",
751
+							  "Data"=>$this->output);
752
+
753
+		if (self::_sendHttp ($post_values,$this->paths['jobs']))
754
+		{
755
+			if (self::_parseServerOutput())
756
+			{
757
+				self::_parseJobAttributes();
758
+			}
759
+		}
760
+
761
+		$this->attributes = &$this->job_attributes;
762
+
763
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
764
+		{
765
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
766
+
767
+			if ($this->serveroutput->status == "successfull-ok")
768
+			{
769
+				self::_errorLog(sprintf(_("getting job attributes for %s: "),$job_uri)
770
+							.$this->serveroutput->status,3);
771
+			}
772
+			else
773
+			{
774
+				 self::_errorLog(sprintf(_("getting job attributes for %s: "),$job_uri)
775
+											 .$this->serveroutput->status,1);
776
+			}
777
+
778
+			return $this->serveroutput->status;
779
+		}
780
+
781
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
782
+		self::_errorLog(date("Y-m-d H:i:s : ")
783
+						.basename($_SERVER['PHP_SELF'])
784
+						.sprintf(_("getting jobs attributes of %s : OPERATION FAILED"),
785
+									 $job_uri),3);
786
+
787
+		return false;
788
+	}
789
+
790
+	public function getPrinters()
791
+	{
792
+		// placeholder for vendor extension operation (getAvailablePrinters for CUPS)
793
+		$this->jobs = array_merge($this->jobs,array(''));
794
+		$this->jobs_uri = array_merge($this->jobs_uri,array(''));
795
+		$this->status = array_merge($this->status,array(''));    
796
+	}
797
+
798
+	public function generateError ($error)
799
+	{
800
+		switch ($error)
801
+		{
802
+			case "request_body_malformed":
803
+				$this->error_generation->request_body_malformed = chr(0xFF);
804
+				break;
805
+			default:
806
+				true;
807
+				break;
808
+		}
809
+
810
+		trigger_error(sprintf(_('Setting Error %s'),$error),E_USER_NOTICE);
811
+	}
812 812
     
813
-    public function resetError ($error)
814
-    {
815
-        unset ($this->error_generation->$error);
816
-        trigger_error(sprintf(_('Reset Error %s'),$error),E_USER_NOTICE);
817
-    }
818
-
819
-    // SETUP
820
-    protected function _setOperationId ()
821
-    {
822
-            $prepend = '';
823
-            $this->operation_id += 1;
824
-            $this->meta->operation_id = self::_integerBuild($this->operation_id);
825
-            self::_putDebug( "operation id is: ".$this->operation_id."\n",2);
826
-    }
813
+	public function resetError ($error)
814
+	{
815
+		unset ($this->error_generation->$error);
816
+		trigger_error(sprintf(_('Reset Error %s'),$error),E_USER_NOTICE);
817
+	}
818
+
819
+	// SETUP
820
+	protected function _setOperationId ()
821
+	{
822
+			$prepend = '';
823
+			$this->operation_id += 1;
824
+			$this->meta->operation_id = self::_integerBuild($this->operation_id);
825
+			self::_putDebug( "operation id is: ".$this->operation_id."\n",2);
826
+	}
827 827
     
828
-    protected function _setJobId()
829
-    {
830
-
831
-        $this->meta->jobid +=1;
832
-        $prepend = '';
833
-        $prepend_length = 4 - strlen($this->meta->jobid);
834
-        for ($i = 0; $i < $prepend_length ; $i++ )
835
-        {
836
-            $prepend .= '0';
837
-        }
838
-
839
-    return $prepend.$this->meta->jobid;
840
-    }
828
+	protected function _setJobId()
829
+	{
830
+
831
+		$this->meta->jobid +=1;
832
+		$prepend = '';
833
+		$prepend_length = 4 - strlen($this->meta->jobid);
834
+		for ($i = 0; $i < $prepend_length ; $i++ )
835
+		{
836
+			$prepend .= '0';
837
+		}
838
+
839
+	return $prepend.$this->meta->jobid;
840
+	}
841 841
     
842
-    protected function _setJobUri ($job_uri)
843
-    {
844
-        $this->meta->job_uri = chr(0x45) // type uri
845
-                             . chr(0x00).chr(0x07) // name-length
846
-                             . "job-uri"
847
-                             //. chr(0x00).chr(strlen($job_uri))
848
-                             . self::_giveMeStringLength($job_uri)
849
-                             . $job_uri;
842
+	protected function _setJobUri ($job_uri)
843
+	{
844
+		$this->meta->job_uri = chr(0x45) // type uri
845
+							 . chr(0x00).chr(0x07) // name-length
846
+							 . "job-uri"
847
+							 //. chr(0x00).chr(strlen($job_uri))
848
+							 . self::_giveMeStringLength($job_uri)
849
+							 . $job_uri;
850 850
         
851
-        self::_putDebug( "job-uri is: ".$job_uri."\n",2);
852
-    }
853
-
854
-    // RESPONSE PARSING
855
-    protected function _parsePrinterAttributes()
856
-    {
857
-        //if (!preg_match('#successful#',$this->serveroutput->status))
858
-        //   return false;
859
-
860
-        $k = -1;
861
-        $l = 0;
862
-        for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
863
-        {
864
-            for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
865
-            {
866
-                if (!empty($this->serveroutput->response[$i][$j]['name']))
867
-                {
868
-                    $k++;
869
-                    $l = 0;
870
-                    $this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
871
-                    $this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
872
-                    $this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
873
-                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
874
-                }
875
-                else
876
-                {
877
-                    $l ++;
878
-                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
879
-                    }
880
-            }
881
-        }
882
-        $this->serveroutput->response = array();
883
-
884
-        $this->printer_attributes = new \stdClass();
885
-        for ($i = 0 ; $i < count($this->parsed) ; $i ++)
886
-        {
887
-                    $name = $this->parsed[$i]['name'];
888
-                    $php_name = str_replace('-','_',$name);
889
-                    $type = $this->parsed[$i]['type'];
890
-                    $range = $this->parsed[$i]['range'];
891
-                    $this->printer_attributes->$php_name = new \stdClass();
892
-                    $this->printer_attributes->$php_name->_type = $type;
893
-                    $this->printer_attributes->$php_name->_range = $range;
894
-                    for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j ++)
895
-                    {
896
-                        $value = $this->parsed[$i][$j];
897
-                        $index = '_value'.$j;
898
-                        $this->printer_attributes->$php_name->$index = $value;
899
-                        }
900
-                    }
901
-
902
-        $this->parsed = array();
903
-    }
904
-
905
-    protected function _parseJobsAttributes()
906
-    {
907
-        //if ($this->serveroutput->status != "successfull-ok")
908
-        //    return false;
909
-
910
-        $job = -1;
911
-        $l = 0;
912
-        for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
913
-        {
914
-            if ($this->serveroutput->response[$i]['attributes'] == "job-attributes")
915
-            {
916
-                $job ++;
917
-            }
918
-            $k = -1; 
919
-            for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
920
-            {
921
-                if (!empty($this->serveroutput->response[$i][$j]['name']))
922
-                {
923
-                    $k++;
924
-                    $l = 0;
925
-                    $this->parsed[$job][$k]['range'] = $this->serveroutput->response[$i]['attributes'];
926
-                    $this->parsed[$job][$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
927
-                    $this->parsed[$job][$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
928
-                    $this->parsed[$job][$k][$l] = $this->serveroutput->response[$i][$j]['value'];
929
-                }
930
-                else
931
-                {
932
-                    $l ++;
933
-                    $this->parsed[$job][$k][$l] = $this->serveroutput->response[$i][$j]['value'];
934
-                }
935
-            }
936
-        }
937
-
938
-        $this->serveroutput->response = array();
939
-        $this->jobs_attributes = new \stdClass();
940
-        for ($job_nbr = 0 ; $job_nbr <= $job ; $job_nbr ++)
941
-        {
942
-            $job_index = "job_".$job_nbr;
943
-            $this->jobs_attributes->$job_index = new \stdClass();
944
-            for ($i = 0 ; $i < count($this->parsed[$job_nbr]) ; $i ++)
945
-            {
946
-                $name = $this->parsed[$job_nbr][$i]['name'];
947
-                $php_name = str_replace('-','_',$name);
948
-                $type = $this->parsed[$job_nbr][$i]['type'];
949
-                $range = $this->parsed[$job_nbr][$i]['range'];
950
-                $this->jobs_attributes->$job_index->$php_name = new \stdClass();
951
-                $this->jobs_attributes->$job_index->$php_name->_type = $type;
952
-                $this->jobs_attributes->$job_index->$php_name->_range = $range;
953
-                for ($j = 0 ; $j < (count($this->parsed[$job_nbr][$i]) - 3) ; $j ++)
954
-                {
955
-                    # This causes incorrect parsing of integer job attributes.
956
-                    # 2010-08-16
957
-                    # bpkroth
958
-                    #$value = self::_interpretAttribute($name,$type,$this->parsed[$job_nbr][$i][$j]);
959
-                    $value = $this->parsed[$job_nbr][$i][$j];
960
-                    $index = '_value'.$j;
961
-                    $this->jobs_attributes->$job_index->$php_name->$index = $value;
962
-                }
963
-            }
964
-        }
965
-
966
-        $this->parsed = array();
967
-    }
968
-
969
-    protected function _readAttribute($attributes_type)
970
-    {
971
-        $tag = ord($this->serveroutput->body[$this->_parsing->offset]);
972
-
973
-        $this->_parsing->offset += 1;
974
-        $j = $this->index;
975
-
976
-        $tag = self::_readTag($tag);
977
-
978
-        switch ($tag)
979
-        {
980
-            case "begCollection": //RFC3382 (BLIND CODE)
981
-                if ($this->end_collection)
982
-                {
983
-                    $this->index --;
984
-                }
985
-                $this->end_collection = false;
986
-                $this->serveroutput->response[$attributes_type][$j]['type'] = "collection";
987
-                self::_putDebug( "tag is: begCollection\n");
988
-                self::_readAttributeName ($attributes_type,$j);
989
-                if (!$this->serveroutput->response[$attributes_type][$j]['name'])
990
-                { // it is a multi-valued collection
991
-                    $this->collection_depth ++;
992
-                    $this->index --;
993
-                    $this->collection_nbr[$this->collection_depth] ++;
994
-                }
995
-                else
996
-                {
997
-                    $this->collection_depth ++;
998
-                    if ($this->collection_depth == 0)
999
-                    {
1000
-                        $this->collection = (object) 'collection';
1001
-                    }
1002
-                    if (array_key_exists($this->collection_depth,$this->collection_nbr))
1003
-                    {
1004
-                        $this->collection_nbr[$this->collection_depth] ++;
1005
-                    }
1006
-                    else
1007
-                    {
1008
-                        $this->collection_nbr[$this->collection_depth] = 0;
1009
-                    }
1010
-                    unset($this->end_collection);
1011
-                }
1012
-                self::_readValue ("begCollection",$attributes_type,$j);
1013
-                break;
1014
-            case "endCollection": //RFC3382 (BLIND CODE)
1015
-                $this->serveroutput->response[$attributes_type][$j]['type'] = "collection";
1016
-                self::_putDebug( "tag is: endCollection\n");
1017
-                self::_readAttributeName ($attributes_type,$j,0);
1018
-                self::_readValue ('name',$attributes_type,$j,0);
1019
-                $this->collection_depth --;
1020
-                $this->collection_key[$this->collection_depth] = 0;
1021
-                $this->end_collection = true;
1022
-                break;
1023
-            case "memberAttrName": // RFC3382 (BLIND CODE)
1024
-                $this->serveroutput->response[$attributes_type][$j]['type'] = "memberAttrName";
1025
-                $this->index -- ;
1026
-                self::_putDebug( "tag is: memberAttrName\n");
1027
-                self::_readCollection ($attributes_type,$j);
1028
-                break;
1029
-
1030
-            default:
1031
-                $this->collection_depth = -1;
1032
-                $this->collection_key = array();
1033
-                $this->collection_nbr = array();
1034
-                $this->serveroutput->response[$attributes_type][$j]['type'] = $tag;
1035
-                self::_putDebug( "tag is: $tag\n");
1036
-                $attribute_name = self::_readAttributeName ($attributes_type,$j);
1037
-                if (!$attribute_name)
1038
-                {
1039
-                    $attribute_name = $this->attribute_name;
1040
-                }
1041
-                else
1042
-                {
1043
-                    $this->attribute_name = $attribute_name;
1044
-                }
1045
-                $value = self::_readValue ($tag,$attributes_type,$j);
1046
-                $this->serveroutput->response[$attributes_type][$j]['value'] = 
1047
-                self::_interpretAttribute($attribute_name,$tag,$this->serveroutput->response[$attributes_type][$j]['value']);
1048
-                break;
1049
-        }
1050
-        return;
1051
-    }
1052
-
1053
-    protected function _readTag($tag)
1054
-    {
1055
-        switch ($tag)
1056
-        {
1057
-            case 0x10:
1058
-                $tag = "unsupported";
1059
-                break;
1060
-            case 0x11:
1061
-                $tag = "reserved for 'default'";
1062
-                break;
1063
-            case 0x12:
1064
-                $tag = "unknown";
1065
-                break;
1066
-            case 0x13:
1067
-                $tag = "no-value";
1068
-                break;
1069
-            case 0x15: // RFC 3380
1070
-                $tag = "not-settable";
1071
-                break;
1072
-            case 0x16: // RFC 3380
1073
-                $tag = "delete-attribute";
1074
-                break;
1075
-            case 0x17: // RFC 3380
1076
-                $tag = "admin-define";
1077
-                break;
1078
-            case 0x20:
1079
-                $tag = "IETF reserved (generic integer)";
1080
-                break;
1081
-            case 0x21:
1082
-                $tag = "integer";
1083
-                break;
1084
-            case 0x22:
1085
-                $tag = "boolean";
1086
-                break;
1087
-            case 0x23:
1088
-                $tag = "enum";
1089
-                break;
1090
-            case 0x30:
1091
-                $tag = "octetString";
1092
-                break;
1093
-            case 0x31:
1094
-                $tag = "datetime";
1095
-                break;
1096
-            case 0x32:
1097
-                $tag = "resolution";
1098
-                break;
1099
-            case 0x33:
1100
-                $tag = "rangeOfInteger";
1101
-                break;
1102
-            case 0x34: //RFC3382 (BLIND CODE)
1103
-                $tag = "begCollection";
1104
-                break;
1105
-            case 0x35:
1106
-                $tag = "textWithLanguage";
1107
-                break;
1108
-            case 0x36:
1109
-                $tag = "nameWithLanguage";
1110
-                break;
1111
-            case 0x37: //RFC3382 (BLIND CODE)
1112
-                $tag = "endCollection";
1113
-                break;
1114
-            case 0x40:
1115
-                $tag = "IETF reserved text string";
1116
-                break;
1117
-            case 0x41:
1118
-                $tag = "textWithoutLanguage";
1119
-                break;
1120
-            case 0x42:
1121
-                $tag = "nameWithoutLanguage";
1122
-                break;
1123
-            case 0x43:
1124
-                $tag = "IETF reserved for future";
1125
-                break;
1126
-            case 0x44:
1127
-                $tag = "keyword";
1128
-                break;
1129
-            case 0x45:
1130
-                $tag = "uri";
1131
-                break;
1132
-            case 0x46:
1133
-                $tag = "uriScheme";
1134
-                break;
1135
-            case 0x47:
1136
-                $tag = "charset";
1137
-                break;
1138
-            case 0x48:
1139
-                $tag = "naturalLanguage";
1140
-                break;
1141
-            case 0x49:
1142
-                $tag = "mimeMediaType";
1143
-                break;
1144
-            case 0x4A: // RFC3382 (BLIND CODE)
1145
-                $tag = "memberAttrName";
1146
-                break;
1147
-            case 0x7F:
1148
-                $tag = "extended type";
1149
-                break;
1150
-            default:
1151
-                if ($tag >= 0x14 && $tag < 0x15 && $tag > 0x17 && $tag <= 0x1f) 
1152
-                {
1153
-                    $tag = "out-of-band";
1154
-                }
1155
-                elseif (0x24 <= $tag && $tag <= 0x2f) 
1156
-                {
1157
-                    $tag = "new integer type";
1158
-                }
1159
-                elseif (0x38 <= $tag && $tag <= 0x3F) 
1160
-                {
1161
-                    $tag = "new octet-stream type";
1162
-                }
1163
-                elseif (0x4B <= $tag && $tag <= 0x5F) 
1164
-                {
1165
-                    $tag = "new character string type";
1166
-                }
1167
-                elseif ((0x60 <= $tag && $tag < 0x7f) || $tag >= 0x80 )
1168
-                {
1169
-                    $tag = "IETF reserved for future";
1170
-                }
1171
-                else
1172
-                {
1173
-                    $tag = sprintf("UNKNOWN: 0x%x (%u)",$tag,$tag);
1174
-                }
1175
-                break;                                                            
1176
-        }
1177
-
1178
-        return $tag; 
1179
-    }
1180
-
1181
-    protected function _readCollection($attributes_type,$j)
1182
-    {
1183
-        $name_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1184
-                     +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1185
-
1186
-        $this->_parsing->offset += 2;
1187
-
1188
-        self::_putDebug( "Collection name_length ". $name_length ."\n");
1189
-
1190
-        $name = '';
1191
-        for ($i = 0; $i < $name_length; $i++)
1192
-        {
1193
-            $name .= $this->serveroutput->body[$this->_parsing->offset];
1194
-            $this->_parsing->offset += 1;
1195
-            if ($this->_parsing->offset > strlen($this->serveroutput->body))
1196
-            {
1197
-                return;
1198
-            }
1199
-        }
1200
-
1201
-        $collection_name = $name;
1202
-
1203
-        $name_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1204
-                     +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1205
-        $this->_parsing->offset += 2;
1206
-
1207
-        self::_putDebug( "Attribute name_length ". $name_length ."\n");
1208
-
1209
-        $name = '';
1210
-        for ($i = 0; $i < $name_length; $i++)
1211
-        {
1212
-            $name .= $this->serveroutput->body[$this->_parsing->offset];
1213
-            $this->_parsing->offset += 1;
1214
-            if ($this->_parsing->offset > strlen($this->serveroutput->body))
1215
-            {
1216
-                return;
1217
-            }
1218
-        }
1219
-
1220
-        $attribute_name = $name;
1221
-        if ($attribute_name == "")
1222
-        {
1223
-            $attribute_name = $this->last_attribute_name;
1224
-            $this->collection_key[$this->collection_depth] ++;
1225
-        }
1226
-        else
1227
-        {
1228
-            $this->collection_key[$this->collection_depth] = 0;
1229
-        }
1230
-        $this->last_attribute_name = $attribute_name;
1231
-
1232
-        self::_putDebug( "Attribute name ".$name."\n");
1233
-
1234
-        $tag = self::_readTag(ord($this->serveroutput->body[$this->_parsing->offset]));
1235
-        $this->_parsing->offset ++;
1236
-
1237
-        $type = $tag;
1238
-
1239
-        $name_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1240
-                     +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1241
-        $this->_parsing->offset += 2;
1242
-
1243
-        self::_putDebug( "Collection2 name_length ". $name_length ."\n");
1244
-
1245
-        $name = '';
1246
-        for ($i = 0; $i < $name_length; $i++)
1247
-        {
1248
-            $name .= $this->serveroutput->body[$this->_parsing->offset];
1249
-            $this->_parsing->offset += 1;
1250
-            if ($this->_parsing->offset > strlen($this->serveroutput->body))
1251
-            {
1252
-                return;
1253
-            }
1254
-        }
1255
-
1256
-        $collection_value = $name;
1257
-        $value_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1258
-                      +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1259
-
1260
-        self::_putDebug( "Collection value_length ".$this->serveroutput->body[ $this->_parsing->offset]
1261
-                                       . $this->serveroutput->body[$this->_parsing->offset + 1]
1262
-                                       .": "
1263
-                                       . $value_length
1264
-                                       . " ");
1265
-
1266
-        $this->_parsing->offset += 2;
1267
-
1268
-        $value = '';
1269
-        for ($i = 0; $i < $value_length; $i++)
1270
-        {
1271
-            if ($this->_parsing->offset >= strlen($this->serveroutput->body))
1272
-            {
1273
-                return;
1274
-            }
1275
-            $value .= $this->serveroutput->body[$this->_parsing->offset];
1276
-            $this->_parsing->offset += 1;
1277
-        }
1278
-
1279
-        $object = &$this->collection;
1280
-        for ($i = 0 ; $i <= $this->collection_depth ; $i ++)
1281
-        {
1282
-            $indice = "_indice".$this->collection_nbr[$i];
1283
-            if (!isset($object->$indice))
1284
-            {
1285
-                $object->$indice = (object) 'indice';
1286
-            }
1287
-            $object = &$object->$indice;
1288
-        }
1289
-
1290
-        $value_key = "_value".$this->collection_key[$this->collection_depth];
1291
-        $col_name_key = "_collection_name".$this->collection_key[$this->collection_depth];
1292
-        $col_val_key = "_collection_value".$this->collection_key[$this->collection_depth];
1293
-
1294
-        $attribute_value = self::_interpretAttribute($attribute_name,$tag,$value);
1295
-        $attribute_name = str_replace('-','_',$attribute_name);
1296
-
1297
-        self::_putDebug( sprintf("Value: %s\n",$value));
1298
-        $object->$attribute_name->_type = $type;
1299
-        $object->$attribute_name->$value_key = $attribute_value;
1300
-        $object->$attribute_name->$col_name_key = $collection_name;
1301
-        $object->$attribute_name->$col_val_key = $collection_value;
1302
-
1303
-        $this->serveroutput->response[$attributes_type][$j]['value'] = $this->collection;
1304
-    }
1305
-
1306
-    protected function _readAttributeName ($attributes_type,$j,$write=1)
1307
-    {
1308
-        $name_length = ord($this->serveroutput->body[ $this->_parsing->offset]) *  256
1309
-                     +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1310
-        $this->_parsing->offset += 2;
1311
-
1312
-        self::_putDebug( "name_length ". $name_length ."\n");
1313
-
1314
-        $name = '';
1315
-        for ($i = 0; $i < $name_length; $i++)
1316
-        {
1317
-            if ($this->_parsing->offset >= strlen($this->serveroutput->body))
1318
-            {
1319
-                return;
1320
-            }
1321
-            $name .= $this->serveroutput->body[$this->_parsing->offset];
1322
-            $this->_parsing->offset += 1;
1323
-        }
1324
-
1325
-        if($write)
1326
-        {
1327
-            $this->serveroutput->response[$attributes_type][$j]['name'] = $name;
1328
-        }
1329
-
1330
-        self::_putDebug( "name " . $name . "\n");
1331
-
1332
-        return $name;   
1333
-    }
1334
-
1335
-    protected function _readValue ($type,$attributes_type,$j,$write=1)
1336
-    {
1337
-        $value_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1338
-                      +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
851
+		self::_putDebug( "job-uri is: ".$job_uri."\n",2);
852
+	}
853
+
854
+	// RESPONSE PARSING
855
+	protected function _parsePrinterAttributes()
856
+	{
857
+		//if (!preg_match('#successful#',$this->serveroutput->status))
858
+		//   return false;
859
+
860
+		$k = -1;
861
+		$l = 0;
862
+		for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
863
+		{
864
+			for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
865
+			{
866
+				if (!empty($this->serveroutput->response[$i][$j]['name']))
867
+				{
868
+					$k++;
869
+					$l = 0;
870
+					$this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
871
+					$this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
872
+					$this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
873
+					$this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
874
+				}
875
+				else
876
+				{
877
+					$l ++;
878
+					$this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
879
+					}
880
+			}
881
+		}
882
+		$this->serveroutput->response = array();
883
+
884
+		$this->printer_attributes = new \stdClass();
885
+		for ($i = 0 ; $i < count($this->parsed) ; $i ++)
886
+		{
887
+					$name = $this->parsed[$i]['name'];
888
+					$php_name = str_replace('-','_',$name);
889
+					$type = $this->parsed[$i]['type'];
890
+					$range = $this->parsed[$i]['range'];
891
+					$this->printer_attributes->$php_name = new \stdClass();
892
+					$this->printer_attributes->$php_name->_type = $type;
893
+					$this->printer_attributes->$php_name->_range = $range;
894
+					for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j ++)
895
+					{
896
+						$value = $this->parsed[$i][$j];
897
+						$index = '_value'.$j;
898
+						$this->printer_attributes->$php_name->$index = $value;
899
+						}
900
+					}
901
+
902
+		$this->parsed = array();
903
+	}
904
+
905
+	protected function _parseJobsAttributes()
906
+	{
907
+		//if ($this->serveroutput->status != "successfull-ok")
908
+		//    return false;
909
+
910
+		$job = -1;
911
+		$l = 0;
912
+		for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
913
+		{
914
+			if ($this->serveroutput->response[$i]['attributes'] == "job-attributes")
915
+			{
916
+				$job ++;
917
+			}
918
+			$k = -1; 
919
+			for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
920
+			{
921
+				if (!empty($this->serveroutput->response[$i][$j]['name']))
922
+				{
923
+					$k++;
924
+					$l = 0;
925
+					$this->parsed[$job][$k]['range'] = $this->serveroutput->response[$i]['attributes'];
926
+					$this->parsed[$job][$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
927
+					$this->parsed[$job][$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
928
+					$this->parsed[$job][$k][$l] = $this->serveroutput->response[$i][$j]['value'];
929
+				}
930
+				else
931
+				{
932
+					$l ++;
933
+					$this->parsed[$job][$k][$l] = $this->serveroutput->response[$i][$j]['value'];
934
+				}
935
+			}
936
+		}
937
+
938
+		$this->serveroutput->response = array();
939
+		$this->jobs_attributes = new \stdClass();
940
+		for ($job_nbr = 0 ; $job_nbr <= $job ; $job_nbr ++)
941
+		{
942
+			$job_index = "job_".$job_nbr;
943
+			$this->jobs_attributes->$job_index = new \stdClass();
944
+			for ($i = 0 ; $i < count($this->parsed[$job_nbr]) ; $i ++)
945
+			{
946
+				$name = $this->parsed[$job_nbr][$i]['name'];
947
+				$php_name = str_replace('-','_',$name);
948
+				$type = $this->parsed[$job_nbr][$i]['type'];
949
+				$range = $this->parsed[$job_nbr][$i]['range'];
950
+				$this->jobs_attributes->$job_index->$php_name = new \stdClass();
951
+				$this->jobs_attributes->$job_index->$php_name->_type = $type;
952
+				$this->jobs_attributes->$job_index->$php_name->_range = $range;
953
+				for ($j = 0 ; $j < (count($this->parsed[$job_nbr][$i]) - 3) ; $j ++)
954
+				{
955
+					# This causes incorrect parsing of integer job attributes.
956
+					# 2010-08-16
957
+					# bpkroth
958
+					#$value = self::_interpretAttribute($name,$type,$this->parsed[$job_nbr][$i][$j]);
959
+					$value = $this->parsed[$job_nbr][$i][$j];
960
+					$index = '_value'.$j;
961
+					$this->jobs_attributes->$job_index->$php_name->$index = $value;
962
+				}
963
+			}
964
+		}
965
+
966
+		$this->parsed = array();
967
+	}
968
+
969
+	protected function _readAttribute($attributes_type)
970
+	{
971
+		$tag = ord($this->serveroutput->body[$this->_parsing->offset]);
972
+
973
+		$this->_parsing->offset += 1;
974
+		$j = $this->index;
975
+
976
+		$tag = self::_readTag($tag);
977
+
978
+		switch ($tag)
979
+		{
980
+			case "begCollection": //RFC3382 (BLIND CODE)
981
+				if ($this->end_collection)
982
+				{
983
+					$this->index --;
984
+				}
985
+				$this->end_collection = false;
986
+				$this->serveroutput->response[$attributes_type][$j]['type'] = "collection";
987
+				self::_putDebug( "tag is: begCollection\n");
988
+				self::_readAttributeName ($attributes_type,$j);
989
+				if (!$this->serveroutput->response[$attributes_type][$j]['name'])
990
+				{ // it is a multi-valued collection
991
+					$this->collection_depth ++;
992
+					$this->index --;
993
+					$this->collection_nbr[$this->collection_depth] ++;
994
+				}
995
+				else
996
+				{
997
+					$this->collection_depth ++;
998
+					if ($this->collection_depth == 0)
999
+					{
1000
+						$this->collection = (object) 'collection';
1001
+					}
1002
+					if (array_key_exists($this->collection_depth,$this->collection_nbr))
1003
+					{
1004
+						$this->collection_nbr[$this->collection_depth] ++;
1005
+					}
1006
+					else
1007
+					{
1008
+						$this->collection_nbr[$this->collection_depth] = 0;
1009
+					}
1010
+					unset($this->end_collection);
1011
+				}
1012
+				self::_readValue ("begCollection",$attributes_type,$j);
1013
+				break;
1014
+			case "endCollection": //RFC3382 (BLIND CODE)
1015
+				$this->serveroutput->response[$attributes_type][$j]['type'] = "collection";
1016
+				self::_putDebug( "tag is: endCollection\n");
1017
+				self::_readAttributeName ($attributes_type,$j,0);
1018
+				self::_readValue ('name',$attributes_type,$j,0);
1019
+				$this->collection_depth --;
1020
+				$this->collection_key[$this->collection_depth] = 0;
1021
+				$this->end_collection = true;
1022
+				break;
1023
+			case "memberAttrName": // RFC3382 (BLIND CODE)
1024
+				$this->serveroutput->response[$attributes_type][$j]['type'] = "memberAttrName";
1025
+				$this->index -- ;
1026
+				self::_putDebug( "tag is: memberAttrName\n");
1027
+				self::_readCollection ($attributes_type,$j);
1028
+				break;
1029
+
1030
+			default:
1031
+				$this->collection_depth = -1;
1032
+				$this->collection_key = array();
1033
+				$this->collection_nbr = array();
1034
+				$this->serveroutput->response[$attributes_type][$j]['type'] = $tag;
1035
+				self::_putDebug( "tag is: $tag\n");
1036
+				$attribute_name = self::_readAttributeName ($attributes_type,$j);
1037
+				if (!$attribute_name)
1038
+				{
1039
+					$attribute_name = $this->attribute_name;
1040
+				}
1041
+				else
1042
+				{
1043
+					$this->attribute_name = $attribute_name;
1044
+				}
1045
+				$value = self::_readValue ($tag,$attributes_type,$j);
1046
+				$this->serveroutput->response[$attributes_type][$j]['value'] = 
1047
+				self::_interpretAttribute($attribute_name,$tag,$this->serveroutput->response[$attributes_type][$j]['value']);
1048
+				break;
1049
+		}
1050
+		return;
1051
+	}
1052
+
1053
+	protected function _readTag($tag)
1054
+	{
1055
+		switch ($tag)
1056
+		{
1057
+			case 0x10:
1058
+				$tag = "unsupported";
1059
+				break;
1060
+			case 0x11:
1061
+				$tag = "reserved for 'default'";
1062
+				break;
1063
+			case 0x12:
1064
+				$tag = "unknown";
1065
+				break;
1066
+			case 0x13:
1067
+				$tag = "no-value";
1068
+				break;
1069
+			case 0x15: // RFC 3380
1070
+				$tag = "not-settable";
1071
+				break;
1072
+			case 0x16: // RFC 3380
1073
+				$tag = "delete-attribute";
1074
+				break;
1075
+			case 0x17: // RFC 3380
1076
+				$tag = "admin-define";
1077
+				break;
1078
+			case 0x20:
1079
+				$tag = "IETF reserved (generic integer)";
1080
+				break;
1081
+			case 0x21:
1082
+				$tag = "integer";
1083
+				break;
1084
+			case 0x22:
1085
+				$tag = "boolean";
1086
+				break;
1087
+			case 0x23:
1088
+				$tag = "enum";
1089
+				break;
1090
+			case 0x30:
1091
+				$tag = "octetString";
1092
+				break;
1093
+			case 0x31:
1094
+				$tag = "datetime";
1095
+				break;
1096
+			case 0x32:
1097
+				$tag = "resolution";
1098
+				break;
1099
+			case 0x33:
1100
+				$tag = "rangeOfInteger";
1101
+				break;
1102
+			case 0x34: //RFC3382 (BLIND CODE)
1103
+				$tag = "begCollection";
1104
+				break;
1105
+			case 0x35:
1106
+				$tag = "textWithLanguage";
1107
+				break;
1108
+			case 0x36:
1109
+				$tag = "nameWithLanguage";
1110
+				break;
1111
+			case 0x37: //RFC3382 (BLIND CODE)
1112
+				$tag = "endCollection";
1113
+				break;
1114
+			case 0x40:
1115
+				$tag = "IETF reserved text string";
1116
+				break;
1117
+			case 0x41:
1118
+				$tag = "textWithoutLanguage";
1119
+				break;
1120
+			case 0x42:
1121
+				$tag = "nameWithoutLanguage";
1122
+				break;
1123
+			case 0x43:
1124
+				$tag = "IETF reserved for future";
1125
+				break;
1126
+			case 0x44:
1127
+				$tag = "keyword";
1128
+				break;
1129
+			case 0x45:
1130
+				$tag = "uri";
1131
+				break;
1132
+			case 0x46:
1133
+				$tag = "uriScheme";
1134
+				break;
1135
+			case 0x47:
1136
+				$tag = "charset";
1137
+				break;
1138
+			case 0x48:
1139
+				$tag = "naturalLanguage";
1140
+				break;
1141
+			case 0x49:
1142
+				$tag = "mimeMediaType";
1143
+				break;
1144
+			case 0x4A: // RFC3382 (BLIND CODE)
1145
+				$tag = "memberAttrName";
1146
+				break;
1147
+			case 0x7F:
1148
+				$tag = "extended type";
1149
+				break;
1150
+			default:
1151
+				if ($tag >= 0x14 && $tag < 0x15 && $tag > 0x17 && $tag <= 0x1f) 
1152
+				{
1153
+					$tag = "out-of-band";
1154
+				}
1155
+				elseif (0x24 <= $tag && $tag <= 0x2f) 
1156
+				{
1157
+					$tag = "new integer type";
1158
+				}
1159
+				elseif (0x38 <= $tag && $tag <= 0x3F) 
1160
+				{
1161
+					$tag = "new octet-stream type";
1162
+				}
1163
+				elseif (0x4B <= $tag && $tag <= 0x5F) 
1164
+				{
1165
+					$tag = "new character string type";
1166
+				}
1167
+				elseif ((0x60 <= $tag && $tag < 0x7f) || $tag >= 0x80 )
1168
+				{
1169
+					$tag = "IETF reserved for future";
1170
+				}
1171
+				else
1172
+				{
1173
+					$tag = sprintf("UNKNOWN: 0x%x (%u)",$tag,$tag);
1174
+				}
1175
+				break;                                                            
1176
+		}
1177
+
1178
+		return $tag; 
1179
+	}
1180
+
1181
+	protected function _readCollection($attributes_type,$j)
1182
+	{
1183
+		$name_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1184
+					 +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1185
+
1186
+		$this->_parsing->offset += 2;
1187
+
1188
+		self::_putDebug( "Collection name_length ". $name_length ."\n");
1189
+
1190
+		$name = '';
1191
+		for ($i = 0; $i < $name_length; $i++)
1192
+		{
1193
+			$name .= $this->serveroutput->body[$this->_parsing->offset];
1194
+			$this->_parsing->offset += 1;
1195
+			if ($this->_parsing->offset > strlen($this->serveroutput->body))
1196
+			{
1197
+				return;
1198
+			}
1199
+		}
1200
+
1201
+		$collection_name = $name;
1202
+
1203
+		$name_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1204
+					 +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1205
+		$this->_parsing->offset += 2;
1206
+
1207
+		self::_putDebug( "Attribute name_length ". $name_length ."\n");
1208
+
1209
+		$name = '';
1210
+		for ($i = 0; $i < $name_length; $i++)
1211
+		{
1212
+			$name .= $this->serveroutput->body[$this->_parsing->offset];
1213
+			$this->_parsing->offset += 1;
1214
+			if ($this->_parsing->offset > strlen($this->serveroutput->body))
1215
+			{
1216
+				return;
1217
+			}
1218
+		}
1219
+
1220
+		$attribute_name = $name;
1221
+		if ($attribute_name == "")
1222
+		{
1223
+			$attribute_name = $this->last_attribute_name;
1224
+			$this->collection_key[$this->collection_depth] ++;
1225
+		}
1226
+		else
1227
+		{
1228
+			$this->collection_key[$this->collection_depth] = 0;
1229
+		}
1230
+		$this->last_attribute_name = $attribute_name;
1231
+
1232
+		self::_putDebug( "Attribute name ".$name."\n");
1233
+
1234
+		$tag = self::_readTag(ord($this->serveroutput->body[$this->_parsing->offset]));
1235
+		$this->_parsing->offset ++;
1236
+
1237
+		$type = $tag;
1238
+
1239
+		$name_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1240
+					 +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1241
+		$this->_parsing->offset += 2;
1242
+
1243
+		self::_putDebug( "Collection2 name_length ". $name_length ."\n");
1244
+
1245
+		$name = '';
1246
+		for ($i = 0; $i < $name_length; $i++)
1247
+		{
1248
+			$name .= $this->serveroutput->body[$this->_parsing->offset];
1249
+			$this->_parsing->offset += 1;
1250
+			if ($this->_parsing->offset > strlen($this->serveroutput->body))
1251
+			{
1252
+				return;
1253
+			}
1254
+		}
1255
+
1256
+		$collection_value = $name;
1257
+		$value_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1258
+					  +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1259
+
1260
+		self::_putDebug( "Collection value_length ".$this->serveroutput->body[ $this->_parsing->offset]
1261
+									   . $this->serveroutput->body[$this->_parsing->offset + 1]
1262
+									   .": "
1263
+									   . $value_length
1264
+									   . " ");
1265
+
1266
+		$this->_parsing->offset += 2;
1267
+
1268
+		$value = '';
1269
+		for ($i = 0; $i < $value_length; $i++)
1270
+		{
1271
+			if ($this->_parsing->offset >= strlen($this->serveroutput->body))
1272
+			{
1273
+				return;
1274
+			}
1275
+			$value .= $this->serveroutput->body[$this->_parsing->offset];
1276
+			$this->_parsing->offset += 1;
1277
+		}
1278
+
1279
+		$object = &$this->collection;
1280
+		for ($i = 0 ; $i <= $this->collection_depth ; $i ++)
1281
+		{
1282
+			$indice = "_indice".$this->collection_nbr[$i];
1283
+			if (!isset($object->$indice))
1284
+			{
1285
+				$object->$indice = (object) 'indice';
1286
+			}
1287
+			$object = &$object->$indice;
1288
+		}
1289
+
1290
+		$value_key = "_value".$this->collection_key[$this->collection_depth];
1291
+		$col_name_key = "_collection_name".$this->collection_key[$this->collection_depth];
1292
+		$col_val_key = "_collection_value".$this->collection_key[$this->collection_depth];
1293
+
1294
+		$attribute_value = self::_interpretAttribute($attribute_name,$tag,$value);
1295
+		$attribute_name = str_replace('-','_',$attribute_name);
1296
+
1297
+		self::_putDebug( sprintf("Value: %s\n",$value));
1298
+		$object->$attribute_name->_type = $type;
1299
+		$object->$attribute_name->$value_key = $attribute_value;
1300
+		$object->$attribute_name->$col_name_key = $collection_name;
1301
+		$object->$attribute_name->$col_val_key = $collection_value;
1302
+
1303
+		$this->serveroutput->response[$attributes_type][$j]['value'] = $this->collection;
1304
+	}
1305
+
1306
+	protected function _readAttributeName ($attributes_type,$j,$write=1)
1307
+	{
1308
+		$name_length = ord($this->serveroutput->body[ $this->_parsing->offset]) *  256
1309
+					 +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1310
+		$this->_parsing->offset += 2;
1311
+
1312
+		self::_putDebug( "name_length ". $name_length ."\n");
1313
+
1314
+		$name = '';
1315
+		for ($i = 0; $i < $name_length; $i++)
1316
+		{
1317
+			if ($this->_parsing->offset >= strlen($this->serveroutput->body))
1318
+			{
1319
+				return;
1320
+			}
1321
+			$name .= $this->serveroutput->body[$this->_parsing->offset];
1322
+			$this->_parsing->offset += 1;
1323
+		}
1324
+
1325
+		if($write)
1326
+		{
1327
+			$this->serveroutput->response[$attributes_type][$j]['name'] = $name;
1328
+		}
1329
+
1330
+		self::_putDebug( "name " . $name . "\n");
1331
+
1332
+		return $name;   
1333
+	}
1334
+
1335
+	protected function _readValue ($type,$attributes_type,$j,$write=1)
1336
+	{
1337
+		$value_length = ord($this->serveroutput->body[$this->_parsing->offset]) *  256
1338
+					  +  ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1339 1339
         
1340
-        self::_putDebug( "value_length ".$this->serveroutput->body[ $this->_parsing->offset]
1341
-                                       . $this->serveroutput->body[$this->_parsing->offset + 1]
1342
-                                       .": "
1343
-                                       . $value_length
1344
-                                       . " ");
1345
-
1346
-        $this->_parsing->offset += 2;
1347
-
1348
-        $value = '';
1349
-        for ($i = 0; $i < $value_length; $i++)
1350
-        {
1351
-            if ($this->_parsing->offset >= strlen($this->serveroutput->body))
1352
-            {
1353
-                return;
1354
-            }
1355
-            $value .= $this->serveroutput->body[$this->_parsing->offset];
1356
-            $this->_parsing->offset += 1;
1357
-            }
1358
-
1359
-        self::_putDebug( sprintf("Value: %s\n",$value));
1360
-
1361
-        if ($write)
1362
-        {
1363
-            $this->serveroutput->response[$attributes_type][$j]['value'] = $value;
1364
-        }
1365
-
1366
-        return $value;
1367
-    }
1368
-
1369
-    protected function _parseAttributes()
1370
-    {
1371
-        $k = -1;
1372
-        $l = 0;
1373
-        for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
1374
-        {
1375
-            for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
1376
-            {
1377
-                if (!empty($this->serveroutput->response[$i][$j]['name']))
1378
-                {
1379
-                    $k++;
1380
-                    $l = 0;
1381
-                    $this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
1382
-                    $this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
1383
-                    $this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
1384
-                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1385
-                }
1386
-                else
1387
-                {
1388
-                    $l ++;
1389
-                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1390
-                }
1391
-            }
1392
-        }
1393
-        $this->serveroutput->response = array();
1394
-        $this->attributes  = new \stdClass();
1395
-        for ($i = 0 ; $i < count($this->parsed) ; $i ++)
1396
-        {
1397
-                    $name = $this->parsed[$i]['name'];
1398
-                    $php_name = str_replace('-','_',$name);
1399
-                    $type = $this->parsed[$i]['type'];
1400
-                    $range = $this->parsed[$i]['range'];
1401
-                    $this->attributes->$php_name = new \stdClass();
1402
-                    $this->attributes->$php_name->_type = $type;
1403
-                    $this->attributes->$php_name->_range = $range;
1404
-                    for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j ++)
1405
-                    {
1406
-                        $value = $this->parsed[$i][$j];
1407
-                        $index = '_value'.$j;
1408
-                        $this->attributes->$php_name->$index = $value;
1409
-                        }
1410
-                    }
1411
-
1412
-        $this->parsed = array();
1413
-    }
1414
-
1415
-    protected function _parseJobAttributes()
1416
-    {
1417
-        //if (!preg_match('#successful#',$this->serveroutput->status))
1418
-        //    return false;
1419
-        $k = -1;
1420
-        $l = 0;
1421
-        for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
1422
-        {
1423
-            for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
1424
-            {
1425
-                if (!empty($this->serveroutput->response[$i][$j]['name']))
1426
-                {
1427
-                    $k++;
1428
-                    $l = 0;
1429
-                    $this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
1430
-                    $this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
1431
-                    $this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
1432
-                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1433
-                }
1434
-                else
1435
-                {
1436
-                    $l ++;
1437
-                    $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1438
-                }
1439
-            }
1440
-        }
1441
-
1442
-        $this->serveroutput->response = array();
1443
-
1444
-        $this->job_attributes = new \stdClass();
1445
-        for ($i = 0 ; $i < count($this->parsed) ; $i ++)
1446
-        {
1447
-                    $name = $this->parsed[$i]['name'];
1448
-                    $php_name = str_replace('-','_',$name);
1449
-                    $type = $this->parsed[$i]['type'];
1450
-                    $range = $this->parsed[$i]['range'];
1451
-                    $this->job_attributes->$php_name = new \stdClass();
1452
-                    $this->job_attributes->$php_name->_type = $type;
1453
-                    $this->job_attributes->$php_name->_range = $range;
1454
-                    for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j ++)
1455
-                    {
1456
-                        $value = $this->parsed[$i][$j];
1457
-                        $index = '_value'.$j;
1458
-                        $this->job_attributes->$php_name->$index = $value;
1459
-                        }
1460
-                    }
1461
-
1462
-        $this->parsed = array();
1463
-    }
1464
-
1465
-    protected function _interpretAttribute($attribute_name,$type,$value)
1466
-    {
1467
-        switch ($type)
1468
-        {
1469
-            case "integer":
1470
-                $value = self::_interpretInteger($value);
1471
-                break;
1472
-            case "rangeOfInteger":
1473
-                $value = self::_interpretRangeOfInteger($value);
1474
-                break;
1475
-            case 'boolean':
1476
-                $value = ord($value);
1477
-                if ($value == 0x00)
1478
-                {
1479
-                    $value = 'false';
1480
-                }
1481
-                else
1482
-                {
1483
-                    $value = 'true';
1484
-                }
1485
-                break;
1486
-            case 'datetime':
1487
-                $value = self::_interpretDateTime($value);
1488
-                break;
1489
-            case 'enum':
1490
-                $value = $this->_interpretEnum($attribute_name,$value); // must be overwritten by children
1491
-                break;
1492
-            case 'resolution':
1493
-                $unit = $value[8];
1494
-                $value = self::_interpretRangeOfInteger(substr($value,0,8));
1495
-                switch($unit)
1496
-                {
1497
-                    case chr(0x03):
1498
-                        $unit = "dpi";
1499
-                        break;
1500
-                    case chr(0x04):
1501
-                        $unit = "dpc";
1502
-                        break;
1503
-                    }
1504
-                $value = $value." ".$unit;
1505
-                break;
1506
-            default:
1507
-                break;
1508
-        }
1509
-        return $value;
1510
-    }
1511
-
1512
-    protected function _interpretRangeOfInteger($value)
1513
-    {
1514
-        $value_parsed = 0;
1515
-        $integer1 = $integer2 = 0;
1516
-
1517
-        $halfsize = strlen($value) / 2;
1518
-
1519
-        $integer1 = self::_interpretInteger(substr($value,0,$halfsize));
1520
-        $integer2 = self::_interpretInteger(substr($value,$halfsize,$halfsize));
1521
-
1522
-        $value_parsed = sprintf('%s-%s',$integer1,$integer2);
1523
-
1524
-        return $value_parsed;
1525
-    }
1526
-
1527
-    protected function _interpretDateTime($date)
1528
-    {
1529
-        $year = self::_interpretInteger(substr($date,0,2));
1530
-        $month =  self::_interpretInteger(substr($date,2,1));
1531
-        $day =  self::_interpretInteger(substr($date,3,1));
1532
-        $hour =  self::_interpretInteger(substr($date,4,1));
1533
-        $minute =  self::_interpretInteger(substr($date,5,1));
1534
-        $second =  self::_interpretInteger(substr($date,6,1));
1535
-        $direction = substr($date,8,1);
1536
-        $hours_from_utc = self::_interpretInteger(substr($date,9,1));
1537
-        $minutes_from_utc = self::_interpretInteger(substr($date,10,1));
1538
-
1539
-        $date = sprintf('%s-%s-%s %s:%s:%s %s%s:%s',$year,$month,$day,$hour,$minute,$second,$direction,$hours_from_utc,$minutes_from_utc);
1540
-
1541
-        return $date;
1542
-    }
1543
-
1544
-    protected function _interpretEnum($attribute_name,$value)
1545
-    {
1546
-        $value_parsed = self::_interpretInteger($value);
1547
-
1548
-        switch ($attribute_name)
1549
-        {
1550
-            case 'job-state':
1551
-                switch ($value_parsed)
1552
-                {
1553
-                    case 0x03:
1554
-                        $value = 'pending';
1555
-                        break;
1556
-                    case 0x04:
1557
-                        $value = 'pending-held';
1558
-                        break;
1559
-                    case 0x05:
1560
-                        $value = 'processing';
1561
-                        break;
1562
-                    case 0x06:
1563
-                        $value = 'processing-stopped';
1564
-                        break;
1565
-                    case 0x07:
1566
-                        $value = 'canceled';
1567
-                        break;
1568
-                    case 0x08:
1569
-                        $value = 'aborted';
1570
-                        break;
1571
-                    case 0x09:
1572
-                        $value = 'completed';
1573
-                        break;
1574
-                }
1575
-                if ($value_parsed > 0x09)
1576
-                {
1577
-                    $value = sprintf('Unknown(IETF standards track "job-state" reserved): 0x%x',$value_parsed);
1578
-                }
1579
-                break;
1580
-            case 'print-quality':
1581
-            case 'print-quality-supported':
1582
-            case 'print-quality-default':
1583
-                switch ($value_parsed)
1584
-                {
1585
-                    case 0x03:
1586
-                        $value = 'draft';
1587
-                        break;
1588
-                    case 0x04:
1589
-                        $value = 'normal';
1590
-                        break;
1591
-                    case 0x05:
1592
-                        $value = 'high';
1593
-                        break;
1594
-                    }
1595
-                break;
1596
-            case 'printer-state':
1597
-                switch ($value_parsed)
1598
-                {
1599
-                    case 0x03:
1600
-                        $value = 'idle';
1601
-                        break;
1602
-                    case 0x04:
1603
-                        $value = 'processing';
1604
-                        break;
1605
-                    case 0x05:
1606
-                        $value = 'stopped';
1607
-                        break;
1608
-                }
1609
-                if ($value_parsed > 0x05)
1610
-                {
1611
-                    $value = sprintf('Unknown(IETF standards track "printer-state" reserved): 0x%x',$value_parsed);
1612
-                }
1613
-                break;
1614
-
1615
-            case 'operations-supported':
1616
-                switch($value_parsed)
1617
-                {
1618
-                    case 0x0000:
1619
-                    case 0x0001:
1620
-                        $value = sprintf('Unknown(reserved) : %s',ord($value));
1621
-                        break;
1622
-                    case 0x0002:
1623
-                        $value = 'Print-Job';
1624
-                        break;
1625
-                    case 0x0003:
1626
-                        $value = 'Print-URI';
1627
-                        break;
1628
-                    case 0x0004:
1629
-                        $value = 'Validate-Job';
1630
-                        break;
1631
-                    case 0x0005:
1632
-                        $value = 'Create-Job';
1633
-                        break;
1634
-                    case 0x0006:
1635
-                        $value = 'Send-Document';
1636
-                        break;
1637
-                    case 0x0007:
1638
-                        $value = 'Send-URI';
1639
-                        break;
1640
-                    case 0x0008:
1641
-                        $value = 'Cancel-Job';
1642
-                        break;
1643
-                    case 0x0009:
1644
-                        $value = 'Get-Job-Attributes';
1645
-                        break;
1646
-                    case 0x000A:
1647
-                        $value = 'Get-Jobs';
1648
-                        break;
1649
-                    case 0x000B:
1650
-                        $value = 'Get-Printer-Attributes';
1651
-                        break;
1652
-                    case 0x000C:
1653
-                        $value = 'Hold-Job';
1654
-                        break;
1655
-                    case 0x000D:
1656
-                        $value = 'Release-Job';
1657
-                        break;
1658
-                    case 0x000E:
1659
-                        $value = 'Restart-Job';
1660
-                        break;
1661
-                    case 0x000F:
1662
-                        $value = 'Unknown(reserved for a future operation)';
1663
-                        break;
1664
-                    case 0x0010:
1665
-                        $value = 'Pause-Printer';
1666
-                        break;
1667
-                    case 0x0011:
1668
-                        $value = 'Resume-Printer';
1669
-                        break;
1670
-                    case 0x0012:
1671
-                        $value = 'Purge-Jobs';
1672
-                        break;
1673
-                    case 0x0013:
1674
-                        $value = 'Set-Printer-Attributes'; // RFC3380
1675
-                        break;
1676
-                    case 0x0014:
1677
-                        $value = 'Set-Job-Attributes'; // RFC3380
1678
-                        break;
1679
-                    case 0x0015:
1680
-                        $value = 'Get-Printer-Supported-Values'; // RFC3380
1681
-                        break;
1682
-                    case 0x0016:
1683
-                        $value = 'Create-Printer-Subscriptions';
1684
-                        break;
1685
-                    case 0x0017:
1686
-                        $value = 'Create-Job-Subscriptions';
1687
-                        break;
1688
-                    case 0x0018:
1689
-                        $value = 'Get-Subscription-Attributes';
1690
-                        break;
1691
-                    case 0x0019:
1692
-                        $value = 'Get-Subscriptions';
1693
-                        break;
1694
-                    case 0x001A:
1695
-                        $value = 'Renew-Subscription';
1696
-                        break;
1697
-                    case 0x001B:
1698
-                        $value = 'Cancel-Subscription';
1699
-                        break;
1700
-                    case 0x001C:
1701
-                        $value = 'Get-Notifications';
1702
-                        break;
1703
-                    case 0x001D:
1704
-                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1705
-                        break;
1706
-                    case 0x001E:
1707
-                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1708
-                        break;
1709
-                    case 0x001F:
1710
-                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1711
-                        break;
1712
-                    case 0x0020:
1713
-                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1714
-                        break;
1715
-                    case 0x0021:
1716
-                        $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1717
-                        break;
1718
-                    case 0x0022: 
1719
-                        $value = 'Enable-Printer';
1720
-                        break;
1721
-                    case 0x0023: 
1722
-                        $value = 'Disable-Printer';
1723
-                        break;
1724
-                    case 0x0024: 
1725
-                        $value = 'Pause-Printer-After-Current-Job';
1726
-                        break;
1727
-                    case 0x0025: 
1728
-                        $value = 'Hold-New-Jobs';
1729
-                        break;
1730
-                    case 0x0026: 
1731
-                        $value = 'Release-Held-New-Jobs';
1732
-                        break;
1733
-                    case 0x0027: 
1734
-                        $value = 'Deactivate-Printer';
1735
-                        break;
1736
-                    case 0x0028: 
1737
-                        $value = 'Activate-Printer';
1738
-                        break;
1739
-                    case 0x0029: 
1740
-                        $value = 'Restart-Printer';
1741
-                        break;
1742
-                    case 0x002A: 
1743
-                        $value = 'Shutdown-Printer';
1744
-                        break;
1745
-                    case 0x002B: 
1746
-                        $value = 'Startup-Printer';
1747
-                        break;
1748
-                }
1749
-                if ($value_parsed > 0x002B && $value_parsed <= 0x3FFF)
1750
-                {
1751
-                    $value = sprintf('Unknown(IETF standards track operations reserved): 0x%x',$value_parsed);
1752
-                }
1753
-                elseif ($value_parsed >= 0x4000 && $value_parsed <= 0x8FFF)
1754
-                {
1755
-                    if (method_exists($this,'_getEnumVendorExtensions'))
1756
-                    {
1757
-                        $value = $this->_getEnumVendorExtensions($value_parsed);
1758
-                    }
1759
-                    else
1760
-                    {
1761
-                        $value = sprintf('Unknown(Vendor extension for operations): 0x%x',$value_parsed);
1762
-                    }
1763
-                }
1764
-                elseif ($value_parsed > 0x8FFF)
1765
-                {
1766
-                    $value = sprintf('Unknown operation (should not exists): 0x%x',$value_parsed);
1767
-                }
1768
-
1769
-                break;
1770
-            case 'finishings':
1771
-            case 'finishings-default':
1772
-            case 'finishings-supported':
1773
-                switch ($value_parsed)
1774
-                {
1775
-                    case 3:
1776
-                        $value = 'none';
1777
-                        break;
1778
-                    case 4:
1779
-                        $value = 'staple';
1780
-                        break;
1781
-                    case 5:
1782
-                        $value = 'punch';
1783
-                        break;
1784
-                    case 6:
1785
-                        $value = 'cover';
1786
-                        break;
1787
-                    case 7:
1788
-                        $value = 'bind';
1789
-                        break;
1790
-                    case 8:
1791
-                        $value = 'saddle-stitch';
1792
-                        break;
1793
-                    case 9:
1794
-                        $value = 'edge-stitch';
1795
-                        break;
1796
-                    case 20:
1797
-                        $value = 'staple-top-left';
1798
-                        break;
1799
-                    case 21:
1800
-                        $value = 'staple-bottom-left';
1801
-                        break;
1802
-                    case 22:
1803
-                        $value = 'staple-top-right';
1804
-                        break;
1805
-                    case 23:
1806
-                        $value = 'staple-bottom-right';
1807
-                        break;
1808
-                    case 24:
1809
-                        $value = 'edge-stitch-left';
1810
-                        break;
1811
-                    case 25:
1812
-                        $value = 'edge-stitch-top';
1813
-                        break;
1814
-                    case 26:
1815
-                        $value = 'edge-stitch-right';
1816
-                        break;
1817
-                    case 27:
1818
-                        $value = 'edge-stitch-bottom';
1819
-                        break;
1820
-                    case 28:
1821
-                        $value = 'staple-dual-left';
1822
-                        break;
1823
-                    case 29:
1824
-                        $value = 'staple-dual-top';
1825
-                        break;
1826
-                    case 30:
1827
-                        $value = 'staple-dual-right';
1828
-                        break;
1829
-                    case 31:
1830
-                        $value = 'staple-dual-bottom';
1831
-                        break;
1832
-                }
1833
-                if ($value_parsed > 31)
1834
-                {
1835
-                    $value = sprintf('Unknown(IETF standards track "finishing" reserved): 0x%x',$value_parsed);
1836
-                }
1837
-                break;
1838
-
1839
-            case 'orientation-requested':
1840
-            case 'orientation-requested-supported':
1841
-            case 'orientation-requested-default':
1842
-                switch ($value_parsed)
1843
-                {
1844
-                    case 0x03:
1845
-                        $value = 'portrait';
1846
-                        break;
1847
-                    case 0x04:
1848
-                        $value = 'landscape';
1849
-                        break;
1850
-                    case 0x05:
1851
-                        $value = 'reverse-landscape';
1852
-                        break;
1853
-                    case 0x06:
1854
-                        $value = 'reverse-portrait';
1855
-                        break;
1856
-                }
1857
-                if ($value_parsed > 0x06)
1858
-                {
1859
-                    $value = sprintf('Unknown(IETF standards track "orientation" reserved): 0x%x',$value_parsed);
1860
-                }
1861
-                break;
1862
-
1863
-            default:
1864
-                break;
1865
-        }
1866
-        return $value;
1867
-    }
1868
-
1869
-    protected function _getJobId ()
1870
-    {
1871
-        if (!isset($this->serveroutput->response))
1872
-        {
1873
-            $this->jobs = array_merge($this->jobs,array('NO JOB'));
1874
-        }
1875
-
1876
-        $jobfinded = false;
1877
-        for ($i = 0 ; (!$jobfinded && array_key_exists($i,$this->serveroutput->response)) ; $i ++)
1878
-        {
1879
-            if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
1880
-            {
1881
-                for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
1882
-                {
1883
-                    if ($this->serveroutput->response[$i][$j]['name'] == "job-id")
1884
-                    {
1885
-                        $this->last_job = $this->serveroutput->response[$i][$j]['value'];
1886
-                        $this->jobs = array_merge($this->jobs,array($this->serveroutput->response[$i][$j]['value']));
1887
-                        return;
1888
-                    }
1889
-                }
1890
-            }
1891
-        }
1892
-    }
1893
-
1894
-    protected function _getJobUri ()
1895
-    {
1896
-        if (!isset($this->jobs_uri))
1897
-        {
1898
-            $this->jobs_uri = array();
1899
-        }
1900
-
1901
-        $jobfinded = false;
1902
-        for ($i = 0 ; (!$jobfinded && array_key_exists($i,$this->serveroutput->response)) ; $i ++)
1903
-        {
1904
-            if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
1905
-            {
1906
-                for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
1907
-                {
1908
-                    if ($this->serveroutput->response[$i][$j]['name'] == "job-uri")
1909
-                    {
1910
-                        $this->last_job = $this->serveroutput->response[$i][$j]['value'];
1911
-                        $this->jobs_uri = array_merge($this->jobs_uri,array($this->last_job));
1912
-                        return;
1913
-                    }
1914
-                }
1915
-            }
1916
-        }
1917
-        $this->last_job = '';
1918
-    }
1919
-
1920
-    protected function _parseResponse ()
1340
+		self::_putDebug( "value_length ".$this->serveroutput->body[ $this->_parsing->offset]
1341
+									   . $this->serveroutput->body[$this->_parsing->offset + 1]
1342
+									   .": "
1343
+									   . $value_length
1344
+									   . " ");
1345
+
1346
+		$this->_parsing->offset += 2;
1347
+
1348
+		$value = '';
1349
+		for ($i = 0; $i < $value_length; $i++)
1350
+		{
1351
+			if ($this->_parsing->offset >= strlen($this->serveroutput->body))
1352
+			{
1353
+				return;
1354
+			}
1355
+			$value .= $this->serveroutput->body[$this->_parsing->offset];
1356
+			$this->_parsing->offset += 1;
1357
+			}
1358
+
1359
+		self::_putDebug( sprintf("Value: %s\n",$value));
1360
+
1361
+		if ($write)
1362
+		{
1363
+			$this->serveroutput->response[$attributes_type][$j]['value'] = $value;
1364
+		}
1365
+
1366
+		return $value;
1367
+	}
1368
+
1369
+	protected function _parseAttributes()
1370
+	{
1371
+		$k = -1;
1372
+		$l = 0;
1373
+		for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
1374
+		{
1375
+			for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
1376
+			{
1377
+				if (!empty($this->serveroutput->response[$i][$j]['name']))
1378
+				{
1379
+					$k++;
1380
+					$l = 0;
1381
+					$this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
1382
+					$this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
1383
+					$this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
1384
+					$this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1385
+				}
1386
+				else
1387
+				{
1388
+					$l ++;
1389
+					$this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1390
+				}
1391
+			}
1392
+		}
1393
+		$this->serveroutput->response = array();
1394
+		$this->attributes  = new \stdClass();
1395
+		for ($i = 0 ; $i < count($this->parsed) ; $i ++)
1396
+		{
1397
+					$name = $this->parsed[$i]['name'];
1398
+					$php_name = str_replace('-','_',$name);
1399
+					$type = $this->parsed[$i]['type'];
1400
+					$range = $this->parsed[$i]['range'];
1401
+					$this->attributes->$php_name = new \stdClass();
1402
+					$this->attributes->$php_name->_type = $type;
1403
+					$this->attributes->$php_name->_range = $range;
1404
+					for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j ++)
1405
+					{
1406
+						$value = $this->parsed[$i][$j];
1407
+						$index = '_value'.$j;
1408
+						$this->attributes->$php_name->$index = $value;
1409
+						}
1410
+					}
1411
+
1412
+		$this->parsed = array();
1413
+	}
1414
+
1415
+	protected function _parseJobAttributes()
1416
+	{
1417
+		//if (!preg_match('#successful#',$this->serveroutput->status))
1418
+		//    return false;
1419
+		$k = -1;
1420
+		$l = 0;
1421
+		for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
1422
+		{
1423
+			for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
1424
+			{
1425
+				if (!empty($this->serveroutput->response[$i][$j]['name']))
1426
+				{
1427
+					$k++;
1428
+					$l = 0;
1429
+					$this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
1430
+					$this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
1431
+					$this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
1432
+					$this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1433
+				}
1434
+				else
1435
+				{
1436
+					$l ++;
1437
+					$this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
1438
+				}
1439
+			}
1440
+		}
1441
+
1442
+		$this->serveroutput->response = array();
1443
+
1444
+		$this->job_attributes = new \stdClass();
1445
+		for ($i = 0 ; $i < count($this->parsed) ; $i ++)
1446
+		{
1447
+					$name = $this->parsed[$i]['name'];
1448
+					$php_name = str_replace('-','_',$name);
1449
+					$type = $this->parsed[$i]['type'];
1450
+					$range = $this->parsed[$i]['range'];
1451
+					$this->job_attributes->$php_name = new \stdClass();
1452
+					$this->job_attributes->$php_name->_type = $type;
1453
+					$this->job_attributes->$php_name->_range = $range;
1454
+					for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j ++)
1455
+					{
1456
+						$value = $this->parsed[$i][$j];
1457
+						$index = '_value'.$j;
1458
+						$this->job_attributes->$php_name->$index = $value;
1459
+						}
1460
+					}
1461
+
1462
+		$this->parsed = array();
1463
+	}
1464
+
1465
+	protected function _interpretAttribute($attribute_name,$type,$value)
1466
+	{
1467
+		switch ($type)
1468
+		{
1469
+			case "integer":
1470
+				$value = self::_interpretInteger($value);
1471
+				break;
1472
+			case "rangeOfInteger":
1473
+				$value = self::_interpretRangeOfInteger($value);
1474
+				break;
1475
+			case 'boolean':
1476
+				$value = ord($value);
1477
+				if ($value == 0x00)
1478
+				{
1479
+					$value = 'false';
1480
+				}
1481
+				else
1482
+				{
1483
+					$value = 'true';
1484
+				}
1485
+				break;
1486
+			case 'datetime':
1487
+				$value = self::_interpretDateTime($value);
1488
+				break;
1489
+			case 'enum':
1490
+				$value = $this->_interpretEnum($attribute_name,$value); // must be overwritten by children
1491
+				break;
1492
+			case 'resolution':
1493
+				$unit = $value[8];
1494
+				$value = self::_interpretRangeOfInteger(substr($value,0,8));
1495
+				switch($unit)
1496
+				{
1497
+					case chr(0x03):
1498
+						$unit = "dpi";
1499
+						break;
1500
+					case chr(0x04):
1501
+						$unit = "dpc";
1502
+						break;
1503
+					}
1504
+				$value = $value." ".$unit;
1505
+				break;
1506
+			default:
1507
+				break;
1508
+		}
1509
+		return $value;
1510
+	}
1511
+
1512
+	protected function _interpretRangeOfInteger($value)
1513
+	{
1514
+		$value_parsed = 0;
1515
+		$integer1 = $integer2 = 0;
1516
+
1517
+		$halfsize = strlen($value) / 2;
1518
+
1519
+		$integer1 = self::_interpretInteger(substr($value,0,$halfsize));
1520
+		$integer2 = self::_interpretInteger(substr($value,$halfsize,$halfsize));
1521
+
1522
+		$value_parsed = sprintf('%s-%s',$integer1,$integer2);
1523
+
1524
+		return $value_parsed;
1525
+	}
1526
+
1527
+	protected function _interpretDateTime($date)
1528
+	{
1529
+		$year = self::_interpretInteger(substr($date,0,2));
1530
+		$month =  self::_interpretInteger(substr($date,2,1));
1531
+		$day =  self::_interpretInteger(substr($date,3,1));
1532
+		$hour =  self::_interpretInteger(substr($date,4,1));
1533
+		$minute =  self::_interpretInteger(substr($date,5,1));
1534
+		$second =  self::_interpretInteger(substr($date,6,1));
1535
+		$direction = substr($date,8,1);
1536
+		$hours_from_utc = self::_interpretInteger(substr($date,9,1));
1537
+		$minutes_from_utc = self::_interpretInteger(substr($date,10,1));
1538
+
1539
+		$date = sprintf('%s-%s-%s %s:%s:%s %s%s:%s',$year,$month,$day,$hour,$minute,$second,$direction,$hours_from_utc,$minutes_from_utc);
1540
+
1541
+		return $date;
1542
+	}
1543
+
1544
+	protected function _interpretEnum($attribute_name,$value)
1545
+	{
1546
+		$value_parsed = self::_interpretInteger($value);
1547
+
1548
+		switch ($attribute_name)
1549
+		{
1550
+			case 'job-state':
1551
+				switch ($value_parsed)
1552
+				{
1553
+					case 0x03:
1554
+						$value = 'pending';
1555
+						break;
1556
+					case 0x04:
1557
+						$value = 'pending-held';
1558
+						break;
1559
+					case 0x05:
1560
+						$value = 'processing';
1561
+						break;
1562
+					case 0x06:
1563
+						$value = 'processing-stopped';
1564
+						break;
1565
+					case 0x07:
1566
+						$value = 'canceled';
1567
+						break;
1568
+					case 0x08:
1569
+						$value = 'aborted';
1570
+						break;
1571
+					case 0x09:
1572
+						$value = 'completed';
1573
+						break;
1574
+				}
1575
+				if ($value_parsed > 0x09)
1576
+				{
1577
+					$value = sprintf('Unknown(IETF standards track "job-state" reserved): 0x%x',$value_parsed);
1578
+				}
1579
+				break;
1580
+			case 'print-quality':
1581
+			case 'print-quality-supported':
1582
+			case 'print-quality-default':
1583
+				switch ($value_parsed)
1584
+				{
1585
+					case 0x03:
1586
+						$value = 'draft';
1587
+						break;
1588
+					case 0x04:
1589
+						$value = 'normal';
1590
+						break;
1591
+					case 0x05:
1592
+						$value = 'high';
1593
+						break;
1594
+					}
1595
+				break;
1596
+			case 'printer-state':
1597
+				switch ($value_parsed)
1598
+				{
1599
+					case 0x03:
1600
+						$value = 'idle';
1601
+						break;
1602
+					case 0x04:
1603
+						$value = 'processing';
1604
+						break;
1605
+					case 0x05:
1606
+						$value = 'stopped';
1607
+						break;
1608
+				}
1609
+				if ($value_parsed > 0x05)
1610
+				{
1611
+					$value = sprintf('Unknown(IETF standards track "printer-state" reserved): 0x%x',$value_parsed);
1612
+				}
1613
+				break;
1614
+
1615
+			case 'operations-supported':
1616
+				switch($value_parsed)
1617
+				{
1618
+					case 0x0000:
1619
+					case 0x0001:
1620
+						$value = sprintf('Unknown(reserved) : %s',ord($value));
1621
+						break;
1622
+					case 0x0002:
1623
+						$value = 'Print-Job';
1624
+						break;
1625
+					case 0x0003:
1626
+						$value = 'Print-URI';
1627
+						break;
1628
+					case 0x0004:
1629
+						$value = 'Validate-Job';
1630
+						break;
1631
+					case 0x0005:
1632
+						$value = 'Create-Job';
1633
+						break;
1634
+					case 0x0006:
1635
+						$value = 'Send-Document';
1636
+						break;
1637
+					case 0x0007:
1638
+						$value = 'Send-URI';
1639
+						break;
1640
+					case 0x0008:
1641
+						$value = 'Cancel-Job';
1642
+						break;
1643
+					case 0x0009:
1644
+						$value = 'Get-Job-Attributes';
1645
+						break;
1646
+					case 0x000A:
1647
+						$value = 'Get-Jobs';
1648
+						break;
1649
+					case 0x000B:
1650
+						$value = 'Get-Printer-Attributes';
1651
+						break;
1652
+					case 0x000C:
1653
+						$value = 'Hold-Job';
1654
+						break;
1655
+					case 0x000D:
1656
+						$value = 'Release-Job';
1657
+						break;
1658
+					case 0x000E:
1659
+						$value = 'Restart-Job';
1660
+						break;
1661
+					case 0x000F:
1662
+						$value = 'Unknown(reserved for a future operation)';
1663
+						break;
1664
+					case 0x0010:
1665
+						$value = 'Pause-Printer';
1666
+						break;
1667
+					case 0x0011:
1668
+						$value = 'Resume-Printer';
1669
+						break;
1670
+					case 0x0012:
1671
+						$value = 'Purge-Jobs';
1672
+						break;
1673
+					case 0x0013:
1674
+						$value = 'Set-Printer-Attributes'; // RFC3380
1675
+						break;
1676
+					case 0x0014:
1677
+						$value = 'Set-Job-Attributes'; // RFC3380
1678
+						break;
1679
+					case 0x0015:
1680
+						$value = 'Get-Printer-Supported-Values'; // RFC3380
1681
+						break;
1682
+					case 0x0016:
1683
+						$value = 'Create-Printer-Subscriptions';
1684
+						break;
1685
+					case 0x0017:
1686
+						$value = 'Create-Job-Subscriptions';
1687
+						break;
1688
+					case 0x0018:
1689
+						$value = 'Get-Subscription-Attributes';
1690
+						break;
1691
+					case 0x0019:
1692
+						$value = 'Get-Subscriptions';
1693
+						break;
1694
+					case 0x001A:
1695
+						$value = 'Renew-Subscription';
1696
+						break;
1697
+					case 0x001B:
1698
+						$value = 'Cancel-Subscription';
1699
+						break;
1700
+					case 0x001C:
1701
+						$value = 'Get-Notifications';
1702
+						break;
1703
+					case 0x001D:
1704
+						$value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1705
+						break;
1706
+					case 0x001E:
1707
+						$value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1708
+						break;
1709
+					case 0x001F:
1710
+						$value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1711
+						break;
1712
+					case 0x0020:
1713
+						$value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1714
+						break;
1715
+					case 0x0021:
1716
+						$value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
1717
+						break;
1718
+					case 0x0022: 
1719
+						$value = 'Enable-Printer';
1720
+						break;
1721
+					case 0x0023: 
1722
+						$value = 'Disable-Printer';
1723
+						break;
1724
+					case 0x0024: 
1725
+						$value = 'Pause-Printer-After-Current-Job';
1726
+						break;
1727
+					case 0x0025: 
1728
+						$value = 'Hold-New-Jobs';
1729
+						break;
1730
+					case 0x0026: 
1731
+						$value = 'Release-Held-New-Jobs';
1732
+						break;
1733
+					case 0x0027: 
1734
+						$value = 'Deactivate-Printer';
1735
+						break;
1736
+					case 0x0028: 
1737
+						$value = 'Activate-Printer';
1738
+						break;
1739
+					case 0x0029: 
1740
+						$value = 'Restart-Printer';
1741
+						break;
1742
+					case 0x002A: 
1743
+						$value = 'Shutdown-Printer';
1744
+						break;
1745
+					case 0x002B: 
1746
+						$value = 'Startup-Printer';
1747
+						break;
1748
+				}
1749
+				if ($value_parsed > 0x002B && $value_parsed <= 0x3FFF)
1750
+				{
1751
+					$value = sprintf('Unknown(IETF standards track operations reserved): 0x%x',$value_parsed);
1752
+				}
1753
+				elseif ($value_parsed >= 0x4000 && $value_parsed <= 0x8FFF)
1754
+				{
1755
+					if (method_exists($this,'_getEnumVendorExtensions'))
1756
+					{
1757
+						$value = $this->_getEnumVendorExtensions($value_parsed);
1758
+					}
1759
+					else
1760
+					{
1761
+						$value = sprintf('Unknown(Vendor extension for operations): 0x%x',$value_parsed);
1762
+					}
1763
+				}
1764
+				elseif ($value_parsed > 0x8FFF)
1765
+				{
1766
+					$value = sprintf('Unknown operation (should not exists): 0x%x',$value_parsed);
1767
+				}
1768
+
1769
+				break;
1770
+			case 'finishings':
1771
+			case 'finishings-default':
1772
+			case 'finishings-supported':
1773
+				switch ($value_parsed)
1774
+				{
1775
+					case 3:
1776
+						$value = 'none';
1777
+						break;
1778
+					case 4:
1779
+						$value = 'staple';
1780
+						break;
1781
+					case 5:
1782
+						$value = 'punch';
1783
+						break;
1784
+					case 6:
1785
+						$value = 'cover';
1786
+						break;
1787
+					case 7:
1788
+						$value = 'bind';
1789
+						break;
1790
+					case 8:
1791
+						$value = 'saddle-stitch';
1792
+						break;
1793
+					case 9:
1794
+						$value = 'edge-stitch';
1795
+						break;
1796
+					case 20:
1797
+						$value = 'staple-top-left';
1798
+						break;
1799
+					case 21:
1800
+						$value = 'staple-bottom-left';
1801
+						break;
1802
+					case 22:
1803
+						$value = 'staple-top-right';
1804
+						break;
1805
+					case 23:
1806
+						$value = 'staple-bottom-right';
1807
+						break;
1808
+					case 24:
1809
+						$value = 'edge-stitch-left';
1810
+						break;
1811
+					case 25:
1812
+						$value = 'edge-stitch-top';
1813
+						break;
1814
+					case 26:
1815
+						$value = 'edge-stitch-right';
1816
+						break;
1817
+					case 27:
1818
+						$value = 'edge-stitch-bottom';
1819
+						break;
1820
+					case 28:
1821
+						$value = 'staple-dual-left';
1822
+						break;
1823
+					case 29:
1824
+						$value = 'staple-dual-top';
1825
+						break;
1826
+					case 30:
1827
+						$value = 'staple-dual-right';
1828
+						break;
1829
+					case 31:
1830
+						$value = 'staple-dual-bottom';
1831
+						break;
1832
+				}
1833
+				if ($value_parsed > 31)
1834
+				{
1835
+					$value = sprintf('Unknown(IETF standards track "finishing" reserved): 0x%x',$value_parsed);
1836
+				}
1837
+				break;
1838
+
1839
+			case 'orientation-requested':
1840
+			case 'orientation-requested-supported':
1841
+			case 'orientation-requested-default':
1842
+				switch ($value_parsed)
1843
+				{
1844
+					case 0x03:
1845
+						$value = 'portrait';
1846
+						break;
1847
+					case 0x04:
1848
+						$value = 'landscape';
1849
+						break;
1850
+					case 0x05:
1851
+						$value = 'reverse-landscape';
1852
+						break;
1853
+					case 0x06:
1854
+						$value = 'reverse-portrait';
1855
+						break;
1856
+				}
1857
+				if ($value_parsed > 0x06)
1858
+				{
1859
+					$value = sprintf('Unknown(IETF standards track "orientation" reserved): 0x%x',$value_parsed);
1860
+				}
1861
+				break;
1862
+
1863
+			default:
1864
+				break;
1865
+		}
1866
+		return $value;
1867
+	}
1868
+
1869
+	protected function _getJobId ()
1870
+	{
1871
+		if (!isset($this->serveroutput->response))
1872
+		{
1873
+			$this->jobs = array_merge($this->jobs,array('NO JOB'));
1874
+		}
1875
+
1876
+		$jobfinded = false;
1877
+		for ($i = 0 ; (!$jobfinded && array_key_exists($i,$this->serveroutput->response)) ; $i ++)
1878
+		{
1879
+			if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
1880
+			{
1881
+				for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
1882
+				{
1883
+					if ($this->serveroutput->response[$i][$j]['name'] == "job-id")
1884
+					{
1885
+						$this->last_job = $this->serveroutput->response[$i][$j]['value'];
1886
+						$this->jobs = array_merge($this->jobs,array($this->serveroutput->response[$i][$j]['value']));
1887
+						return;
1888
+					}
1889
+				}
1890
+			}
1891
+		}
1892
+	}
1893
+
1894
+	protected function _getJobUri ()
1895
+	{
1896
+		if (!isset($this->jobs_uri))
1897
+		{
1898
+			$this->jobs_uri = array();
1899
+		}
1900
+
1901
+		$jobfinded = false;
1902
+		for ($i = 0 ; (!$jobfinded && array_key_exists($i,$this->serveroutput->response)) ; $i ++)
1903
+		{
1904
+			if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
1905
+			{
1906
+				for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
1907
+				{
1908
+					if ($this->serveroutput->response[$i][$j]['name'] == "job-uri")
1909
+					{
1910
+						$this->last_job = $this->serveroutput->response[$i][$j]['value'];
1911
+						$this->jobs_uri = array_merge($this->jobs_uri,array($this->last_job));
1912
+						return;
1913
+					}
1914
+				}
1915
+			}
1916
+		}
1917
+		$this->last_job = '';
1918
+	}
1919
+
1920
+	protected function _parseResponse ()
1921 1921
    {
1922
-        $j = -1;
1923
-        $this->index = 0;
1924
-        for ($i = $this->_parsing->offset; $i < strlen($this->serveroutput->body) ; $i = $this->_parsing->offset)
1925
-        {
1926
-            $tag = ord($this->serveroutput->body[$this->_parsing->offset]);
1927
-
1928
-            if ($tag > 0x0F)
1929
-            {
1930
-                self::_readAttribute($j);
1931
-                $this->index ++;
1932
-                continue;
1933
-            }
1934
-
1935
-            switch ($tag)
1936
-            {
1937
-                case 0x01:
1938
-                    $j += 1;
1939
-                    $this->serveroutput->response[$j]['attributes'] = "operation-attributes";
1940
-                    $this->index = 0;
1941
-                    $this->_parsing->offset += 1;
1942
-                    break;
1943
-                case 0x02:
1944
-                    $j += 1;
1945
-                    $this->serveroutput->response[$j]['attributes'] = "job-attributes";
1946
-                    $this->index = 0;
1947
-                    $this->_parsing->offset += 1;
1948
-                    break;
1949
-                case 0x03:
1950
-                    $j +=1;
1951
-                    $this->serveroutput->response[$j]['attributes'] = "end-of-attributes";
1952
-                    self::_putDebug( "tag is: ".$this->serveroutput->response[$j]['attributes']."\n");
1953
-                    if ($this->alert_on_end_tag === 1)
1954
-                    {
1955
-                        echo "END tag OK<br />";
1956
-                    }
1957
-                    $this->response_completed[(count($this->response_completed) -1)] = "completed";
1958
-                    return;
1959
-                case 0x04:
1960
-                    $j += 1;
1961
-                    $this->serveroutput->response[$j]['attributes'] = "printer-attributes";
1962
-                    $this->index = 0;
1963
-                    $this->_parsing->offset += 1;
1964
-                    break;
1965
-                case 0x05:
1966
-                    $j += 1;
1967
-                    $this->serveroutput->response[$j]['attributes'] = "unsupported-attributes";
1968
-                    $this->index = 0;
1969
-                    $this->_parsing->offset += 1;
1970
-                    break;
1971
-                default:
1972
-                    $j += 1;
1973
-                    $this->serveroutput->response[$j]['attributes'] = sprintf(_("0x%x (%u) : attributes tag Unknown (reserved for future versions of IPP"),$tag,$tag);
1974
-                    $this->index = 0;
1975
-                    $this->_parsing->offset += 1;
1976
-                    break;
1977
-            }
1978
-
1979
-            self::_putDebug( "tag is: ".$this->serveroutput->response[$j]['attributes']."\n\n\n");
1980
-        }
1981
-        return;
1982
-    }
1983
-
1984
-    /*
1922
+		$j = -1;
1923
+		$this->index = 0;
1924
+		for ($i = $this->_parsing->offset; $i < strlen($this->serveroutput->body) ; $i = $this->_parsing->offset)
1925
+		{
1926
+			$tag = ord($this->serveroutput->body[$this->_parsing->offset]);
1927
+
1928
+			if ($tag > 0x0F)
1929
+			{
1930
+				self::_readAttribute($j);
1931
+				$this->index ++;
1932
+				continue;
1933
+			}
1934
+
1935
+			switch ($tag)
1936
+			{
1937
+				case 0x01:
1938
+					$j += 1;
1939
+					$this->serveroutput->response[$j]['attributes'] = "operation-attributes";
1940
+					$this->index = 0;
1941
+					$this->_parsing->offset += 1;
1942
+					break;
1943
+				case 0x02:
1944
+					$j += 1;
1945
+					$this->serveroutput->response[$j]['attributes'] = "job-attributes";
1946
+					$this->index = 0;
1947
+					$this->_parsing->offset += 1;
1948
+					break;
1949
+				case 0x03:
1950
+					$j +=1;
1951
+					$this->serveroutput->response[$j]['attributes'] = "end-of-attributes";
1952
+					self::_putDebug( "tag is: ".$this->serveroutput->response[$j]['attributes']."\n");
1953
+					if ($this->alert_on_end_tag === 1)
1954
+					{
1955
+						echo "END tag OK<br />";
1956
+					}
1957
+					$this->response_completed[(count($this->response_completed) -1)] = "completed";
1958
+					return;
1959
+				case 0x04:
1960
+					$j += 1;
1961
+					$this->serveroutput->response[$j]['attributes'] = "printer-attributes";
1962
+					$this->index = 0;
1963
+					$this->_parsing->offset += 1;
1964
+					break;
1965
+				case 0x05:
1966
+					$j += 1;
1967
+					$this->serveroutput->response[$j]['attributes'] = "unsupported-attributes";
1968
+					$this->index = 0;
1969
+					$this->_parsing->offset += 1;
1970
+					break;
1971
+				default:
1972
+					$j += 1;
1973
+					$this->serveroutput->response[$j]['attributes'] = sprintf(_("0x%x (%u) : attributes tag Unknown (reserved for future versions of IPP"),$tag,$tag);
1974
+					$this->index = 0;
1975
+					$this->_parsing->offset += 1;
1976
+					break;
1977
+			}
1978
+
1979
+			self::_putDebug( "tag is: ".$this->serveroutput->response[$j]['attributes']."\n\n\n");
1980
+		}
1981
+		return;
1982
+	}
1983
+
1984
+	/*
1985 1985
     // NOTICE : HAVE TO READ AGAIN RFC 2911 TO SEE IF IT IS PART OF SERVER'S RESPONSE (CUPS DO NOT)
1986 1986
 
1987 1987
     protected function _getPrinterUri () {
@@ -2002,53 +2002,53 @@  discard block
 block discarded – undo
2002 2002
 
2003 2003
     */
2004 2004
 
2005
-    // REQUEST BUILDING
2006
-    protected function _stringCancel ($job_uri)
2007
-    {
2005
+	// REQUEST BUILDING
2006
+	protected function _stringCancel ($job_uri)
2007
+	{
2008 2008
     
2009
-        if (!isset($this->setup->charset))
2010
-        {
2011
-            self::setCharset();
2012
-        }
2013
-        if (!isset($this->setup->datatype))
2014
-        {
2015
-            self::setBinary();
2016
-        }
2017
-        if (!isset($this->setup->language))
2018
-        {
2019
-            self::setLanguage('en_us');
2020
-        }
2021
-        if (!$this->requesting_user)   
2022
-        {
2023
-            self::setUserName();
2024
-        }
2025
-        if (!isset($this->meta->message))
2026
-        {
2027
-            $this->meta->message = '';
2028
-        }
2029
-
2030
-        self::_setOperationId();
2031
-
2032
-        self::_setJobUri($job_uri);
2033
-
2034
-        if (!isset($this->error_generation->request_body_malformed))
2035
-        {
2036
-            $this->error_generation->request_body_malformed = "";
2037
-        }
2038
-
2039
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
2040
-                         . chr(0x00) . chr (0x08) // cancel-Job | operation-id
2041
-                         . $this->meta->operation_id //           request-id
2042
-                         . $this->error_generation->request_body_malformed
2043
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
2044
-                         . $this->meta->charset
2045
-                         . $this->meta->language
2046
-                         . $this->meta->job_uri
2047
-                         . $this->meta->username
2048
-                         . $this->meta->message
2049
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
2009
+		if (!isset($this->setup->charset))
2010
+		{
2011
+			self::setCharset();
2012
+		}
2013
+		if (!isset($this->setup->datatype))
2014
+		{
2015
+			self::setBinary();
2016
+		}
2017
+		if (!isset($this->setup->language))
2018
+		{
2019
+			self::setLanguage('en_us');
2020
+		}
2021
+		if (!$this->requesting_user)   
2022
+		{
2023
+			self::setUserName();
2024
+		}
2025
+		if (!isset($this->meta->message))
2026
+		{
2027
+			$this->meta->message = '';
2028
+		}
2029
+
2030
+		self::_setOperationId();
2031
+
2032
+		self::_setJobUri($job_uri);
2033
+
2034
+		if (!isset($this->error_generation->request_body_malformed))
2035
+		{
2036
+			$this->error_generation->request_body_malformed = "";
2037
+		}
2038
+
2039
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
2040
+						 . chr(0x00) . chr (0x08) // cancel-Job | operation-id
2041
+						 . $this->meta->operation_id //           request-id
2042
+						 . $this->error_generation->request_body_malformed
2043
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
2044
+						 . $this->meta->charset
2045
+						 . $this->meta->language
2046
+						 . $this->meta->job_uri
2047
+						 . $this->meta->username
2048
+						 . $this->meta->message
2049
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
2050 2050
                          
2051
-        self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
2052
-        return TRUE;
2053
-    }
2051
+		self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
2052
+		return TRUE;
2053
+	}
2054 2054
 }
Please login to merge, or discard this patch.
htdocs/includes/printipp/BasicIPP.php 1 patch
Indentation   +1922 added lines, -1922 removed lines patch added patch discarded remove patch
@@ -40,333 +40,333 @@  discard block
 block discarded – undo
40 40
 
41 41
 class ippException extends \Exception
42 42
 {
43
-    protected $errno;
44
-
45
-    public function __construct($msg, $errno = null)
46
-    {
47
-        parent::__construct($msg);
48
-        $this->errno = $errno;
49
-    }
50
-
51
-    public function getErrorFormatted()
52
-    {
53
-        $return = sprintf("[ipp]: %s -- " . _(" file %s, line %s"),
54
-            $this->getMessage() , $this->getFile() , $this->getLine());
55
-        return $return;
56
-    }
57
-
58
-    public function getErrno()
59
-    {
60
-        return $this->errno;
61
-    }
43
+	protected $errno;
44
+
45
+	public function __construct($msg, $errno = null)
46
+	{
47
+		parent::__construct($msg);
48
+		$this->errno = $errno;
49
+	}
50
+
51
+	public function getErrorFormatted()
52
+	{
53
+		$return = sprintf("[ipp]: %s -- " . _(" file %s, line %s"),
54
+			$this->getMessage() , $this->getFile() , $this->getLine());
55
+		return $return;
56
+	}
57
+
58
+	public function getErrno()
59
+	{
60
+		return $this->errno;
61
+	}
62 62
 }
63 63
 
64 64
 class BasicIPP
65 65
 {
66
-    public $paths = array(
67
-        "root" => "/",
68
-        "admin" => "/admin/",
69
-        "printers" => "/printers/",
70
-        "jobs" => "/jobs/"
71
-    );
72
-    public $http_timeout = 30; // timeout at http connection (seconds) 0 => default => 30.
73
-    public $http_data_timeout = 30; // data reading timeout (milliseconds) 0 => default => 30.
74
-    public $ssl = false;
75
-    public $debug_level = 3; // max 3: almost silent
76
-    public $alert_on_end_tag; // debugging purpose: echo "END tag OK" if (1 and  reads while end tag)
77
-    public $with_exceptions = 1; // compatibility mode for old scripts		// DOL_LDR_CHANGE set this to 1
78
-    public $handle_http_exceptions = 1;
79
-
80
-    // readables variables
81
-    public $jobs = array();
82
-    public $jobs_uri = array();
83
-    public $status = array();
84
-    public $response_completed = array();
85
-    public $last_job = "";
86
-    public $attributes; // object you can read: attributes after validateJob()
87
-    public $printer_attributes; // object you can read: printer's attributes after getPrinterAttributes()
88
-    public $job_attributes; // object you can read: last job attributes
89
-    public $jobs_attributes; // object you can read: jobs attributes after getJobs()
90
-    public $available_printers = array();
91
-    public $printer_map = array();
92
-    public $printers_uri = array();
93
-    public $debug = array();
94
-    public $response;
95
-    public $meta;
96
-
97
-    // protected variables;
98
-    protected $log_level = 2; // max 3: very verbose
99
-    protected $log_type = 3; // 3: file | 1: e-mail | 0: logger
100
-    protected $log_destination; // e-mail or file
101
-    protected $serveroutput;
102
-    protected $setup;
103
-    protected $stringjob;
104
-    protected $data;
105
-    protected $debug_count = 0;
106
-    protected $username;
107
-    protected $charset;
108
-    protected $password;
109
-    protected $requesring_user;
110
-    protected $client_hostname = "localhost";
111
-    protected $stream;
112
-    protected $host = "localhost";
113
-    protected $port = "631";
114
-    protected $requesting_user = '';
115
-    protected $printer_uri;
116
-    protected $timeout = "20"; //20 secs
117
-    protected $errNo;
118
-    protected $errStr;
119
-    protected $datatype;
120
-    protected $datahead;
121
-    protected $datatail;
122
-    protected $operation_id;
123
-    protected $delay;
124
-    protected $error_generation; //devel feature
125
-    protected $debug_http = 0;
126
-    protected $no_disconnect;
127
-    protected $job_tags;
128
-    protected $operation_tags;
129
-    protected $index;
130
-    protected $collection; //RFC3382
131
-    protected $collection_index; //RFC3382
132
-    protected $collection_key = array(); //RFC3382
133
-    protected $collection_depth = - 1; //RFC3382
134
-    protected $end_collection = false; //RFC3382
135
-    protected $collection_nbr = array(); //RFC3382
136
-    protected $unix = false; // true -> use unix sockets instead of http
137
-    protected $output;
138
-
139
-    public function __construct()
140
-    {
141
-        $tz = getenv("date.timezone");
142
-        if (!$tz)
143
-        {
144
-            $tz = @date_default_timezone_get();
145
-        }
146
-
147
-        date_default_timezone_set($tz);
148
-        $this->meta = new \stdClass();
149
-        $this->setup = new \stdClass();
150
-        $this->values = new \stdClass();
151
-        $this->serveroutput = new \stdClass();
152
-        $this->error_generation = new \stdClass();
153
-        $this->_parsing = new \stdClass();
154
-        self::_initTags();
155
-    }
156
-
157
-    public function setPort($port = '631')
158
-    {
159
-        $this->port = $port;
160
-        self::_putDebug("Port is " . $this->port, 2);
161
-    }
162
-
163
-    public function setUnix($socket = '/var/run/cups/cups.sock')
164
-    {
165
-        $this->host = $socket;
166
-        $this->unix = true;
167
-        self::_putDebug("Host is " . $this->host, 2);
168
-    }
169
-
170
-    public function setHost($host = 'localhost')
171
-    {
172
-        $this->host = $host;
173
-        $this->unix = false;
174
-        self::_putDebug("Host is " . $this->host, 2);
175
-    }
176
-
177
-    public function setTimeout($timeout)
178
-    {
179
-        $this->timeout = $timeout;
180
-    }
181
-
182
-    public function setPrinterURI($uri)
183
-    {
184
-        $length = strlen($uri);
185
-        $length = chr($length);
186
-        while (strlen($length) < 2) $length = chr(0x00) . $length;
187
-        $this->meta->printer_uri = chr(0x45) // uri type | value-tag
188
-            . chr(0x00) . chr(0x0B) // name-length
189
-            . "printer-uri" // printer-uri | name
190
-            . $length . $uri;
191
-        $this->printer_uri = $uri;
192
-        self::_putDebug(sprintf(_("Printer URI: %s") , $uri) , 2);
193
-        $this->setup->uri = 1;
194
-    }
195
-
196
-    public function setData($data)
197
-    {
198
-        $this->data = $data;
199
-        self::_putDebug("Data set", 2);
200
-    }
201
-
202
-    public function setRawText()
203
-    {
204
-        $this->setup->datatype = 'TEXT';
205
-        $this->meta->mime_media_type = "";
206
-        $this->setup->mime_media_type = 1;
207
-        $this->datahead = chr(0x16);
208
-        if (is_readable($this->data))
209
-        {
210
-            //It's a filename.  Open and stream.
211
-            $data = fopen($this->data, "rb");
212
-            while (!feof($data)) $output = fread($data, 8192);
213
-        }
214
-        else
215
-        {
216
-            $output = $this->data;
217
-        }
218
-        if (substr($output, -1, 1) != chr(0x0c)) {
219
-            if (!isset($this->setup->noFormFeed))
220
-            {
221
-                $this->datatail = chr(0x0c);
222
-            }
223
-        }
224
-        self::_putDebug(_("Forcing data to be interpreted as RAW TEXT") , 2);
225
-    }
226
-
227
-    public function unsetRawText()
228
-    {
229
-        $this->setup->datatype = 'BINARY';
230
-        $this->datahead = '';
231
-        $this->datatail = '';
232
-        self::_putDebug(_("Unset forcing data to be interpreted as RAW TEXT") , 2);
233
-    }
234
-
235
-    public function setBinary()
236
-    {
237
-        self::unsetRawText();
238
-    }
239
-
240
-    public function setFormFeed()
241
-    {
242
-        $this->datatail = "\r\n" . chr(0x0c);
243
-        unset($this->setup->noFormFeed);
244
-    }
245
-
246
-    public function unsetFormFeed()
247
-    {
248
-        $this->datatail = '';
249
-        $this->setup->noFormFeed = 1;
250
-    }
251
-
252
-    public function setCharset($charset = 'utf-8')
253
-    {
254
-        $charset = strtolower($charset);
255
-        $this->charset = $charset;
256
-        $this->meta->charset = chr(0x47) // charset type | value-tag
257
-            . chr(0x00) . chr(0x12) // name-length
258
-            . "attributes-charset" // attributes-charset | name
259
-            . self::_giveMeStringLength($charset) // value-length
260
-            . $charset; // value
261
-        self::_putDebug(sprintf(_("Charset: %s") , $charset) , 2);
262
-        $this->setup->charset = 1;
263
-    }
264
-
265
-    public function setLanguage($language = 'en_us')
266
-    {
267
-        $language = strtolower($language);
268
-        $this->meta->language = chr(0x48) // natural-language type | value-tag
269
-            . chr(0x00) . chr(0x1B) //  name-length
270
-            . "attributes-natural-language" //attributes-natural-language
271
-            . self::_giveMeStringLength($language) // value-length
272
-            . $language; // value
273
-        self::_putDebug(sprintf(_("Language: %s") , $language) , 2);
274
-        $this->setup->language = 1;
275
-    }
276
-
277
-    public function setDocumentFormat($mime_media_type = 'application/octet-stream')
278
-    {
279
-        self::setBinary();
280
-        $length = chr(strlen($mime_media_type));
281
-        while (strlen($length) < 2) $length = chr(0x00) . $length;
282
-        self::_putDebug(sprintf(_("mime type: %s") , $mime_media_type) , 2);
283
-        $this->meta->mime_media_type = chr(0x49) // document-format tag
284
-            . self::_giveMeStringLength('document-format') . 'document-format' //
285
-            . self::_giveMeStringLength($mime_media_type) . $mime_media_type; // value
286
-        $this->setup->mime_media_type = 1;
287
-    }
288
-
289
-    // setDocumentFormat alias for backward compatibility
290
-    public function setMimeMediaType($mime_media_type = "application/octet-stream")
291
-    {
292
-        self::setDocumentFormat($mime_media_type);
293
-    }
294
-
295
-    public function setCopies($nbrcopies = 1)
296
-    {
297
-        $this->meta->copies = "";
298
-
299
-        if ($nbrcopies == 1 || !$nbrcopies)
300
-        {
301
-            return true;
302
-        }
303
-
304
-        $copies = self::_integerBuild($nbrcopies);
305
-        $this->meta->copies = chr(0x21) // integer type | value-tag
306
-            . chr(0x00) . chr(0x06) //             name-length
307
-            . "copies" // copies    |             name
308
-            . self::_giveMeStringLength($copies) // value-length
309
-            . $copies;
310
-        self::_putDebug(sprintf(_("Copies: %s") , $nbrcopies) , 2);
311
-        $this->setup->copies = 1;
312
-    }
313
-
314
-    public function setDocumentName($document_name = "")
315
-    {
316
-        $this->meta->document_name = "";
317
-        if (!$document_name) {
318
-            return true;
319
-        }
320
-        $document_name = substr($document_name, 0, 1023);
321
-        $length = strlen($document_name);
322
-        $length = chr($length);
323
-        while (strlen($length) < 2) $length = chr(0x00) . $length;
324
-        self::_putDebug(sprintf(_("document name: %s") , $document_name) , 2);
325
-        $this->meta->document_name = chr(0x41) // textWithoutLanguage tag
326
-            . chr(0x00) . chr(0x0d) // name-length
327
-            . "document-name" // mimeMediaType
328
-            . self::_giveMeStringLength($document_name) . $document_name; // value
329
-
330
-    }
331
-
332
-    public function setJobName($jobname = '', $absolute = false)
333
-    {
334
-        $this->meta->jobname = '';
335
-        if ($jobname == '')
336
-        {
337
-            $this->meta->jobname = '';
338
-            return true;
339
-        }
340
-        $postpend = date('-H:i:s-') . $this->_setJobId();
341
-        if ($absolute) {
342
-            $postpend = '';
343
-        }
344
-        if (isset($this->values->jobname) && $jobname == '(PHP)')
345
-        {
346
-            $jobname = $this->values->jobname;
347
-        }
348
-        $this->values->jobname = $jobname;
349
-        $jobname.= $postpend;
350
-        $this->meta->jobname = chr(0x42) // nameWithoutLanguage type || value-tag
351
-            . chr(0x00) . chr(0x08) //  name-length
352
-            . "job-name" //  job-name || name
353
-            . self::_giveMeStringLength($jobname) // value-length
354
-            . $jobname; // value
355
-        self::_putDebug(sprintf(_("Job name: %s") , $jobname) , 2);
356
-        $this->setup->jobname = 1;
357
-    }
358
-
359
-    public function setUserName($username = 'PHP-SERVER')
360
-    {
361
-        $this->requesting_user = $username;
362
-        $this->meta->username = '';
363
-        if (!$username) {
364
-            return true;
365
-        }
366
-        if ($username == 'PHP-SERVER' && isset($this->meta->username)) {
367
-            return TRUE;
368
-        }
369
-        /*
66
+	public $paths = array(
67
+		"root" => "/",
68
+		"admin" => "/admin/",
69
+		"printers" => "/printers/",
70
+		"jobs" => "/jobs/"
71
+	);
72
+	public $http_timeout = 30; // timeout at http connection (seconds) 0 => default => 30.
73
+	public $http_data_timeout = 30; // data reading timeout (milliseconds) 0 => default => 30.
74
+	public $ssl = false;
75
+	public $debug_level = 3; // max 3: almost silent
76
+	public $alert_on_end_tag; // debugging purpose: echo "END tag OK" if (1 and  reads while end tag)
77
+	public $with_exceptions = 1; // compatibility mode for old scripts		// DOL_LDR_CHANGE set this to 1
78
+	public $handle_http_exceptions = 1;
79
+
80
+	// readables variables
81
+	public $jobs = array();
82
+	public $jobs_uri = array();
83
+	public $status = array();
84
+	public $response_completed = array();
85
+	public $last_job = "";
86
+	public $attributes; // object you can read: attributes after validateJob()
87
+	public $printer_attributes; // object you can read: printer's attributes after getPrinterAttributes()
88
+	public $job_attributes; // object you can read: last job attributes
89
+	public $jobs_attributes; // object you can read: jobs attributes after getJobs()
90
+	public $available_printers = array();
91
+	public $printer_map = array();
92
+	public $printers_uri = array();
93
+	public $debug = array();
94
+	public $response;
95
+	public $meta;
96
+
97
+	// protected variables;
98
+	protected $log_level = 2; // max 3: very verbose
99
+	protected $log_type = 3; // 3: file | 1: e-mail | 0: logger
100
+	protected $log_destination; // e-mail or file
101
+	protected $serveroutput;
102
+	protected $setup;
103
+	protected $stringjob;
104
+	protected $data;
105
+	protected $debug_count = 0;
106
+	protected $username;
107
+	protected $charset;
108
+	protected $password;
109
+	protected $requesring_user;
110
+	protected $client_hostname = "localhost";
111
+	protected $stream;
112
+	protected $host = "localhost";
113
+	protected $port = "631";
114
+	protected $requesting_user = '';
115
+	protected $printer_uri;
116
+	protected $timeout = "20"; //20 secs
117
+	protected $errNo;
118
+	protected $errStr;
119
+	protected $datatype;
120
+	protected $datahead;
121
+	protected $datatail;
122
+	protected $operation_id;
123
+	protected $delay;
124
+	protected $error_generation; //devel feature
125
+	protected $debug_http = 0;
126
+	protected $no_disconnect;
127
+	protected $job_tags;
128
+	protected $operation_tags;
129
+	protected $index;
130
+	protected $collection; //RFC3382
131
+	protected $collection_index; //RFC3382
132
+	protected $collection_key = array(); //RFC3382
133
+	protected $collection_depth = - 1; //RFC3382
134
+	protected $end_collection = false; //RFC3382
135
+	protected $collection_nbr = array(); //RFC3382
136
+	protected $unix = false; // true -> use unix sockets instead of http
137
+	protected $output;
138
+
139
+	public function __construct()
140
+	{
141
+		$tz = getenv("date.timezone");
142
+		if (!$tz)
143
+		{
144
+			$tz = @date_default_timezone_get();
145
+		}
146
+
147
+		date_default_timezone_set($tz);
148
+		$this->meta = new \stdClass();
149
+		$this->setup = new \stdClass();
150
+		$this->values = new \stdClass();
151
+		$this->serveroutput = new \stdClass();
152
+		$this->error_generation = new \stdClass();
153
+		$this->_parsing = new \stdClass();
154
+		self::_initTags();
155
+	}
156
+
157
+	public function setPort($port = '631')
158
+	{
159
+		$this->port = $port;
160
+		self::_putDebug("Port is " . $this->port, 2);
161
+	}
162
+
163
+	public function setUnix($socket = '/var/run/cups/cups.sock')
164
+	{
165
+		$this->host = $socket;
166
+		$this->unix = true;
167
+		self::_putDebug("Host is " . $this->host, 2);
168
+	}
169
+
170
+	public function setHost($host = 'localhost')
171
+	{
172
+		$this->host = $host;
173
+		$this->unix = false;
174
+		self::_putDebug("Host is " . $this->host, 2);
175
+	}
176
+
177
+	public function setTimeout($timeout)
178
+	{
179
+		$this->timeout = $timeout;
180
+	}
181
+
182
+	public function setPrinterURI($uri)
183
+	{
184
+		$length = strlen($uri);
185
+		$length = chr($length);
186
+		while (strlen($length) < 2) $length = chr(0x00) . $length;
187
+		$this->meta->printer_uri = chr(0x45) // uri type | value-tag
188
+			. chr(0x00) . chr(0x0B) // name-length
189
+			. "printer-uri" // printer-uri | name
190
+			. $length . $uri;
191
+		$this->printer_uri = $uri;
192
+		self::_putDebug(sprintf(_("Printer URI: %s") , $uri) , 2);
193
+		$this->setup->uri = 1;
194
+	}
195
+
196
+	public function setData($data)
197
+	{
198
+		$this->data = $data;
199
+		self::_putDebug("Data set", 2);
200
+	}
201
+
202
+	public function setRawText()
203
+	{
204
+		$this->setup->datatype = 'TEXT';
205
+		$this->meta->mime_media_type = "";
206
+		$this->setup->mime_media_type = 1;
207
+		$this->datahead = chr(0x16);
208
+		if (is_readable($this->data))
209
+		{
210
+			//It's a filename.  Open and stream.
211
+			$data = fopen($this->data, "rb");
212
+			while (!feof($data)) $output = fread($data, 8192);
213
+		}
214
+		else
215
+		{
216
+			$output = $this->data;
217
+		}
218
+		if (substr($output, -1, 1) != chr(0x0c)) {
219
+			if (!isset($this->setup->noFormFeed))
220
+			{
221
+				$this->datatail = chr(0x0c);
222
+			}
223
+		}
224
+		self::_putDebug(_("Forcing data to be interpreted as RAW TEXT") , 2);
225
+	}
226
+
227
+	public function unsetRawText()
228
+	{
229
+		$this->setup->datatype = 'BINARY';
230
+		$this->datahead = '';
231
+		$this->datatail = '';
232
+		self::_putDebug(_("Unset forcing data to be interpreted as RAW TEXT") , 2);
233
+	}
234
+
235
+	public function setBinary()
236
+	{
237
+		self::unsetRawText();
238
+	}
239
+
240
+	public function setFormFeed()
241
+	{
242
+		$this->datatail = "\r\n" . chr(0x0c);
243
+		unset($this->setup->noFormFeed);
244
+	}
245
+
246
+	public function unsetFormFeed()
247
+	{
248
+		$this->datatail = '';
249
+		$this->setup->noFormFeed = 1;
250
+	}
251
+
252
+	public function setCharset($charset = 'utf-8')
253
+	{
254
+		$charset = strtolower($charset);
255
+		$this->charset = $charset;
256
+		$this->meta->charset = chr(0x47) // charset type | value-tag
257
+			. chr(0x00) . chr(0x12) // name-length
258
+			. "attributes-charset" // attributes-charset | name
259
+			. self::_giveMeStringLength($charset) // value-length
260
+			. $charset; // value
261
+		self::_putDebug(sprintf(_("Charset: %s") , $charset) , 2);
262
+		$this->setup->charset = 1;
263
+	}
264
+
265
+	public function setLanguage($language = 'en_us')
266
+	{
267
+		$language = strtolower($language);
268
+		$this->meta->language = chr(0x48) // natural-language type | value-tag
269
+			. chr(0x00) . chr(0x1B) //  name-length
270
+			. "attributes-natural-language" //attributes-natural-language
271
+			. self::_giveMeStringLength($language) // value-length
272
+			. $language; // value
273
+		self::_putDebug(sprintf(_("Language: %s") , $language) , 2);
274
+		$this->setup->language = 1;
275
+	}
276
+
277
+	public function setDocumentFormat($mime_media_type = 'application/octet-stream')
278
+	{
279
+		self::setBinary();
280
+		$length = chr(strlen($mime_media_type));
281
+		while (strlen($length) < 2) $length = chr(0x00) . $length;
282
+		self::_putDebug(sprintf(_("mime type: %s") , $mime_media_type) , 2);
283
+		$this->meta->mime_media_type = chr(0x49) // document-format tag
284
+			. self::_giveMeStringLength('document-format') . 'document-format' //
285
+			. self::_giveMeStringLength($mime_media_type) . $mime_media_type; // value
286
+		$this->setup->mime_media_type = 1;
287
+	}
288
+
289
+	// setDocumentFormat alias for backward compatibility
290
+	public function setMimeMediaType($mime_media_type = "application/octet-stream")
291
+	{
292
+		self::setDocumentFormat($mime_media_type);
293
+	}
294
+
295
+	public function setCopies($nbrcopies = 1)
296
+	{
297
+		$this->meta->copies = "";
298
+
299
+		if ($nbrcopies == 1 || !$nbrcopies)
300
+		{
301
+			return true;
302
+		}
303
+
304
+		$copies = self::_integerBuild($nbrcopies);
305
+		$this->meta->copies = chr(0x21) // integer type | value-tag
306
+			. chr(0x00) . chr(0x06) //             name-length
307
+			. "copies" // copies    |             name
308
+			. self::_giveMeStringLength($copies) // value-length
309
+			. $copies;
310
+		self::_putDebug(sprintf(_("Copies: %s") , $nbrcopies) , 2);
311
+		$this->setup->copies = 1;
312
+	}
313
+
314
+	public function setDocumentName($document_name = "")
315
+	{
316
+		$this->meta->document_name = "";
317
+		if (!$document_name) {
318
+			return true;
319
+		}
320
+		$document_name = substr($document_name, 0, 1023);
321
+		$length = strlen($document_name);
322
+		$length = chr($length);
323
+		while (strlen($length) < 2) $length = chr(0x00) . $length;
324
+		self::_putDebug(sprintf(_("document name: %s") , $document_name) , 2);
325
+		$this->meta->document_name = chr(0x41) // textWithoutLanguage tag
326
+			. chr(0x00) . chr(0x0d) // name-length
327
+			. "document-name" // mimeMediaType
328
+			. self::_giveMeStringLength($document_name) . $document_name; // value
329
+
330
+	}
331
+
332
+	public function setJobName($jobname = '', $absolute = false)
333
+	{
334
+		$this->meta->jobname = '';
335
+		if ($jobname == '')
336
+		{
337
+			$this->meta->jobname = '';
338
+			return true;
339
+		}
340
+		$postpend = date('-H:i:s-') . $this->_setJobId();
341
+		if ($absolute) {
342
+			$postpend = '';
343
+		}
344
+		if (isset($this->values->jobname) && $jobname == '(PHP)')
345
+		{
346
+			$jobname = $this->values->jobname;
347
+		}
348
+		$this->values->jobname = $jobname;
349
+		$jobname.= $postpend;
350
+		$this->meta->jobname = chr(0x42) // nameWithoutLanguage type || value-tag
351
+			. chr(0x00) . chr(0x08) //  name-length
352
+			. "job-name" //  job-name || name
353
+			. self::_giveMeStringLength($jobname) // value-length
354
+			. $jobname; // value
355
+		self::_putDebug(sprintf(_("Job name: %s") , $jobname) , 2);
356
+		$this->setup->jobname = 1;
357
+	}
358
+
359
+	public function setUserName($username = 'PHP-SERVER')
360
+	{
361
+		$this->requesting_user = $username;
362
+		$this->meta->username = '';
363
+		if (!$username) {
364
+			return true;
365
+		}
366
+		if ($username == 'PHP-SERVER' && isset($this->meta->username)) {
367
+			return TRUE;
368
+		}
369
+		/*
370 370
         $value_length = 0x00;
371 371
         for ($i = 0; $i < strlen($username); $i++)
372 372
         {
@@ -375,1610 +375,1610 @@  discard block
 block discarded – undo
375 375
         $value_length = chr($value_length);
376 376
         while (strlen($value_length) < 2) $value_length = chr(0x00) . $value_length;
377 377
         */
378
-        $this->meta->username = chr(0x42) // keyword type || value-tag
379
-            . chr(0x00) . chr(0x14) // name-length
380
-            . "requesting-user-name"
381
-            . self::_giveMeStringLength($username) // value-length
382
-            . $username;
383
-        self::_putDebug(sprintf(_("Username: %s") , $username) , 2);
384
-        $this->setup->username = 1;
385
-    }
386
-
387
-    public function setAuthentification($username, $password)
388
-    {
389
-        self::setAuthentication($username, $password);
390
-    }
391
-
392
-    public function setAuthentication($username, $password)
393
-    {
394
-        $this->password = $password;
395
-        $this->username = $username;
396
-        self::_putDebug(_("Setting password") , 2);
397
-        $this->setup->password = 1;
398
-    }
399
-
400
-    public function setSides($sides = 2)
401
-    {
402
-        $this->meta->sides = '';
403
-        if (!$sides)
404
-        {
405
-            return true;
406
-        }
407
-
408
-        switch ($sides)
409
-        {
410
-            case 1:
411
-                $sides = "one-sided";
412
-                break;
413
-
414
-            case 2:
415
-                $sides = "two-sided-long-edge";
416
-                break;
417
-
418
-            case "2CE":
419
-                $sides = "two-sided-short-edge";
420
-                break;
421
-        }
422
-
423
-        $this->meta->sides = chr(0x44) // keyword type | value-tag
424
-            . chr(0x00) . chr(0x05) //        name-length
425
-            . "sides" // sides |             name
426
-            . self::_giveMeStringLength($sides) //               value-length
427
-            . $sides; // one-sided |          value
428
-        self::_putDebug(sprintf(_("Sides value set to %s") , $sides) , 2);
429
-    }
430
-
431
-    public function setFidelity()
432
-    {
433
-        // whether the server can't replace any attributes
434
-        // (eg, 2 sided print is not possible,
435
-        // so print one sided) and DO NOT THE JOB.
436
-        $this->meta->fidelity = chr(0x22) // boolean type  |  value-tag
437
-            . chr(0x00) . chr(0x16) //                  name-length
438
-            . "ipp-attribute-fidelity" // ipp-attribute-fidelity | name
439
-            . chr(0x00) . chr(0x01) //  value-length
440
-            . chr(0x01); //  true | value
441
-        self::_putDebug(_("Fidelity attribute is set (paranoid mode)") , 3);
442
-    }
443
-
444
-    public function unsetFidelity()
445
-    {
446
-        // whether the server can replace any attributes
447
-        // (eg, 2 sided print is not possible,
448
-        // so print one sided) and DO THE JOB.
449
-        $this->meta->fidelity = chr(0x22) //  boolean type | value-tag
450
-            . chr(0x00) . chr(0x16) //        name-length
451
-            . "ipp-attribute-fidelity" // ipp-attribute-fidelity | name
452
-            . chr(0x00) . chr(0x01) //               value-length
453
-            . chr(0x00); // false |                   value
454
-        self::_putDebug(_("Fidelity attribute is unset") , 2);
455
-    }
456
-
457
-    public function setMessage($message = '')
458
-    {
459
-        $this->meta->message = '';
460
-        if (!$message) {
461
-            return true;
462
-        }
463
-        $this->meta->message =
464
-            chr(0x41) // attribute type = textWithoutLanguage
465
-                . chr(0x00)
466
-                . chr(0x07)
467
-                . "message"
468
-                . self::_giveMeStringLength(substr($message, 0, 127))
469
-                . substr($message, 0, 127);
470
-        self::_putDebug(sprintf(_('Setting message to "%s"') , $message) , 2);
471
-    }
472
-
473
-    public function setPageRanges($page_ranges)
474
-    {
475
-        // $pages_ranges = string:  "1:5 10:25 40:52 ..."
476
-        // to unset, specify an empty string.
477
-        $this->meta->page_range = '';
478
-        if (!$page_ranges) {
479
-            return true;
480
-        }
481
-        $page_ranges = trim(str_replace("-", ":", $page_ranges));
482
-        $first = true;
483
-        #$page_ranges = split(' ', $page_ranges);
484
-        $page_ranges = preg_split('# #', $page_ranges);
485
-        foreach($page_ranges as $page_range)
486
-        {
487
-            $value = self::_rangeOfIntegerBuild($page_range);
488
-            if ($first)
489
-            {
490
-                $this->meta->page_ranges .=
491
-                $this->tags_types['rangeOfInteger']['tag']
492
-                    . self::_giveMeStringLength('page-ranges')
493
-                    . 'page-ranges'
494
-                    . self::_giveMeStringLength($value)
495
-                    . $value;
496
-            }
497
-            else
498
-            {
499
-                $this->meta->page_ranges .=
500
-                $this->tags_types['rangeOfInteger']['tag']
501
-                    . self::_giveMeStringLength('')
502
-                    . self::_giveMeStringLength($value)
503
-                    . $value;
504
-                $first = false;
505
-            }
506
-        }
507
-    }
508
-
509
-    public function setAttribute($attribute, $values)
510
-    {
511
-        $operation_attributes_tags = array_keys($this->operation_tags);
512
-        $job_attributes_tags = array_keys($this->job_tags);
513
-        $printer_attributes_tags = array_keys($this->printer_tags);
514
-        self::unsetAttribute($attribute);
515
-        if (in_array($attribute, $operation_attributes_tags))
516
-        {
517
-            if (!is_array($values))
518
-            {
519
-                self::_setOperationAttribute($attribute, $values);
520
-            }
521
-            else
522
-            {
523
-                foreach($values as $value)
524
-                {
525
-                    self::_setOperationAttribute($attribute, $value);
526
-                }
527
-            }
528
-        }
529
-        elseif (in_array($attribute, $job_attributes_tags))
530
-        {
531
-            if (!is_array($values))
532
-            {
533
-                self::_setJobAttribute($attribute, $values);
534
-            }
535
-            else
536
-            {
537
-                foreach($values as $value)
538
-                {
539
-                    self::_setJobAttribute($attribute, $value);
540
-                }
541
-            }
542
-        }
543
-        elseif (in_array($attribute, $printer_attributes_tags))
544
-        {
545
-            if (!is_array($values))
546
-            {
547
-                self::_setPrinterAttribute($attribute, $values);
548
-            }
549
-            else
550
-            {
551
-                foreach($values as $value)
552
-                {
553
-                    self::_setPrinterAttribute($attribute, $value);
554
-                }
555
-            }
556
-        }
557
-        else
558
-        {
559
-            trigger_error(
560
-                sprintf(_('SetAttribute: Tag "%s" is not a printer or a job attribute'),
561
-                    $attribute) , E_USER_NOTICE);
562
-            self::_putDebug(
563
-                sprintf(_('SetAttribute: Tag "%s" is not a printer or a job attribute'),
564
-                    $attribute) , 3);
565
-            self::_errorLog(
566
-                sprintf(_('SetAttribute: Tag "%s" is not a printer or a job attribute'),
567
-                    $attribute) , 2);
568
-            return FALSE;
569
-        }
570
-    }
571
-
572
-    public function unsetAttribute($attribute)
573
-    {
574
-        $operation_attributes_tags = array_keys($this->operation_tags);
575
-        $job_attributes_tags = array_keys($this->job_tags);
576
-        $printer_attributes_tags = array_keys($this->printer_tags);
577
-        if (in_array($attribute, $operation_attributes_tags))
578
-        {
579
-            unset(
580
-                $this->operation_tags[$attribute]['value'],
581
-                $this->operation_tags[$attribute]['systag']
582
-            );
583
-        }
584
-        elseif (in_array($attribute, $job_attributes_tags))
585
-        {
586
-            unset(
587
-                $this->job_tags[$attribute]['value'],
588
-                $this->job_tags[$attribute]['systag']
589
-            );
590
-        }
591
-        elseif (in_array($attribute, $printer_attributes_tags))
592
-        {
593
-            unset(
594
-                $this->printer_tags[$attribute]['value'],
595
-                $this->printer_tags[$attribute]['systag']
596
-            );
597
-        }
598
-        else
599
-        {
600
-            trigger_error(
601
-                sprintf(_('unsetAttribute: Tag "%s" is not a printer or a job attribute'),
602
-                    $attribute) , E_USER_NOTICE);
603
-            self::_putDebug(
604
-                sprintf(_('unsetAttribute: Tag "%s" is not a printer or a job attribute'),
605
-                    $attribute) , 3);
606
-            self::_errorLog(
607
-                sprintf(_('unsetAttribute: Tag "%s" is not a printer or a job attribute'),
608
-                    $attribute) , 2);
609
-            return FALSE;
610
-        }
611
-        return true;
612
-    }
613
-
614
-    //
615
-    // LOGGING / DEBUGGING
616
-    //
617
-    /**
618
-     * Sets log file destination. Creates the file if has permission.
619
-     *
620
-     * @param string $log_destination
621
-     * @param string $destination_type
622
-     * @param int $level
623
-     *
624
-     * @throws ippException
625
-     */
626
-    public function setLog($log_destination, $destination_type = 'file', $level = 2)
627
-    {
628
-        if (!file_exists($log_destination) && is_writable(dirname($log_destination)))
629
-        {
630
-            touch($log_destination);
631
-            chmod($log_destination, 0777);
632
-        }
633
-
634
-        switch ($destination_type)
635
-        {
636
-            case 'file':
637
-            case 3:
638
-                $this->log_destination = $log_destination;
639
-                $this->log_type = 3;
640
-                break;
641
-
642
-            case 'logger':
643
-            case 0:
644
-                $this->log_destination = '';
645
-                $this->log_type = 0;
646
-                break;
647
-
648
-            case 'e-mail':
649
-            case 1:
650
-                $this->log_destination = $log_destination;
651
-                $this->log_type = 1;
652
-                break;
653
-        }
654
-        $this->log_level = $level;
655
-    }
656
-
657
-    public function printDebug()
658
-    {
659
-        for ($i = 0; $i < $this->debug_count; $i++)
660
-        {
661
-            echo $this->debug[$i], "\n";
662
-        }
663
-        $this->debug = array();
664
-        $this->debug_count = 0;
665
-    }
666
-
667
-    public function getDebug()
668
-    {
669
-        $debug = '';
670
-        for ($i = 0; $i < $this->debug_count; $i++)
671
-        {
672
-            $debug.= $this->debug[$i];
673
-        }
674
-        $this->debug = array();
675
-        $this->debug_count = 0;
676
-        return $debug;
677
-    }
678
-
679
-    //
680
-    // OPERATIONS
681
-    //
682
-    public function printJob()
683
-    {
684
-        // this BASIC version of printJob do not parse server
685
-        // output for job's attributes
686
-        self::_putDebug(
687
-            sprintf(
688
-                "************** Date: %s ***********",
689
-                date('Y-m-d H:i:s')
690
-            )
691
-        );
692
-        if (!$this->_stringJob()) {
693
-            return FALSE;
694
-        }
695
-        if (is_readable($this->data))
696
-        {
697
-            self::_putDebug(_("Printing a FILE"));
698
-            $this->output = $this->stringjob;
699
-            if ($this->setup->datatype == "TEXT")
700
-            {
701
-                $this->output.= chr(0x16);
702
-            }
703
-            $post_values = array(
704
-                "Content-Type" => "application/ipp",
705
-                "Data" => $this->output,
706
-                "File" => $this->data
707
-            );
708
-            if ($this->setup->datatype == "TEXT" && !isset($this->setup->noFormFeed))
709
-            {
710
-                $post_values = array_merge(
711
-                    $post_values,
712
-                    array(
713
-                        "Filetype" => "TEXT"
714
-                    )
715
-                );
716
-            }
717
-        }
718
-        else
719
-        {
720
-            self::_putDebug(_("Printing DATA"));
721
-            $this->output =
722
-                $this->stringjob
723
-                    . $this->datahead
724
-                    . $this->data
725
-                    . $this->datatail;
726
-            $post_values = array(
727
-                "Content-Type" => "application/ipp",
728
-                "Data" => $this->output
729
-            );
730
-        }
731
-        if (self::_sendHttp($post_values, $this->paths["printers"]))
732
-        {
733
-            self::_parseServerOutput();
734
-        }
735
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
736
-        {
737
-            $this->status = array_merge($this->status, array(
738
-                $this->serveroutput->status
739
-            ));
740
-            if ($this->serveroutput->status == "successfull-ok")
741
-            {
742
-                self::_errorLog(
743
-                    sprintf("printing job %s: ", $this->last_job)
744
-                        . $this->serveroutput->status,
745
-                    3);
746
-            }
747
-            else
748
-            {
749
-                self::_errorLog(
750
-                    sprintf("printing job: ", $this->last_job)
751
-                        . $this->serveroutput->status,
752
-                    1);
753
-            }
754
-                return $this->serveroutput->status;
755
-        }
756
-
757
-    $this->status =
758
-        array_merge($this->status, array("OPERATION FAILED"));
759
-        $this->jobs =
760
-            array_merge($this->jobs, array(""));
761
-        $this->jobs_uri =
762
-            array_merge($this->jobs_uri, array(""));
763
-
764
-        self::_errorLog("printing job : OPERATION FAILED", 1);
765
-        return false;
766
-    }
767
-
768
-    //
769
-    // HTTP OUTPUT
770
-    //
771
-    protected function _sendHttp($post_values, $uri)
772
-    {
773
-        /*
378
+		$this->meta->username = chr(0x42) // keyword type || value-tag
379
+			. chr(0x00) . chr(0x14) // name-length
380
+			. "requesting-user-name"
381
+			. self::_giveMeStringLength($username) // value-length
382
+			. $username;
383
+		self::_putDebug(sprintf(_("Username: %s") , $username) , 2);
384
+		$this->setup->username = 1;
385
+	}
386
+
387
+	public function setAuthentification($username, $password)
388
+	{
389
+		self::setAuthentication($username, $password);
390
+	}
391
+
392
+	public function setAuthentication($username, $password)
393
+	{
394
+		$this->password = $password;
395
+		$this->username = $username;
396
+		self::_putDebug(_("Setting password") , 2);
397
+		$this->setup->password = 1;
398
+	}
399
+
400
+	public function setSides($sides = 2)
401
+	{
402
+		$this->meta->sides = '';
403
+		if (!$sides)
404
+		{
405
+			return true;
406
+		}
407
+
408
+		switch ($sides)
409
+		{
410
+			case 1:
411
+				$sides = "one-sided";
412
+				break;
413
+
414
+			case 2:
415
+				$sides = "two-sided-long-edge";
416
+				break;
417
+
418
+			case "2CE":
419
+				$sides = "two-sided-short-edge";
420
+				break;
421
+		}
422
+
423
+		$this->meta->sides = chr(0x44) // keyword type | value-tag
424
+			. chr(0x00) . chr(0x05) //        name-length
425
+			. "sides" // sides |             name
426
+			. self::_giveMeStringLength($sides) //               value-length
427
+			. $sides; // one-sided |          value
428
+		self::_putDebug(sprintf(_("Sides value set to %s") , $sides) , 2);
429
+	}
430
+
431
+	public function setFidelity()
432
+	{
433
+		// whether the server can't replace any attributes
434
+		// (eg, 2 sided print is not possible,
435
+		// so print one sided) and DO NOT THE JOB.
436
+		$this->meta->fidelity = chr(0x22) // boolean type  |  value-tag
437
+			. chr(0x00) . chr(0x16) //                  name-length
438
+			. "ipp-attribute-fidelity" // ipp-attribute-fidelity | name
439
+			. chr(0x00) . chr(0x01) //  value-length
440
+			. chr(0x01); //  true | value
441
+		self::_putDebug(_("Fidelity attribute is set (paranoid mode)") , 3);
442
+	}
443
+
444
+	public function unsetFidelity()
445
+	{
446
+		// whether the server can replace any attributes
447
+		// (eg, 2 sided print is not possible,
448
+		// so print one sided) and DO THE JOB.
449
+		$this->meta->fidelity = chr(0x22) //  boolean type | value-tag
450
+			. chr(0x00) . chr(0x16) //        name-length
451
+			. "ipp-attribute-fidelity" // ipp-attribute-fidelity | name
452
+			. chr(0x00) . chr(0x01) //               value-length
453
+			. chr(0x00); // false |                   value
454
+		self::_putDebug(_("Fidelity attribute is unset") , 2);
455
+	}
456
+
457
+	public function setMessage($message = '')
458
+	{
459
+		$this->meta->message = '';
460
+		if (!$message) {
461
+			return true;
462
+		}
463
+		$this->meta->message =
464
+			chr(0x41) // attribute type = textWithoutLanguage
465
+				. chr(0x00)
466
+				. chr(0x07)
467
+				. "message"
468
+				. self::_giveMeStringLength(substr($message, 0, 127))
469
+				. substr($message, 0, 127);
470
+		self::_putDebug(sprintf(_('Setting message to "%s"') , $message) , 2);
471
+	}
472
+
473
+	public function setPageRanges($page_ranges)
474
+	{
475
+		// $pages_ranges = string:  "1:5 10:25 40:52 ..."
476
+		// to unset, specify an empty string.
477
+		$this->meta->page_range = '';
478
+		if (!$page_ranges) {
479
+			return true;
480
+		}
481
+		$page_ranges = trim(str_replace("-", ":", $page_ranges));
482
+		$first = true;
483
+		#$page_ranges = split(' ', $page_ranges);
484
+		$page_ranges = preg_split('# #', $page_ranges);
485
+		foreach($page_ranges as $page_range)
486
+		{
487
+			$value = self::_rangeOfIntegerBuild($page_range);
488
+			if ($first)
489
+			{
490
+				$this->meta->page_ranges .=
491
+				$this->tags_types['rangeOfInteger']['tag']
492
+					. self::_giveMeStringLength('page-ranges')
493
+					. 'page-ranges'
494
+					. self::_giveMeStringLength($value)
495
+					. $value;
496
+			}
497
+			else
498
+			{
499
+				$this->meta->page_ranges .=
500
+				$this->tags_types['rangeOfInteger']['tag']
501
+					. self::_giveMeStringLength('')
502
+					. self::_giveMeStringLength($value)
503
+					. $value;
504
+				$first = false;
505
+			}
506
+		}
507
+	}
508
+
509
+	public function setAttribute($attribute, $values)
510
+	{
511
+		$operation_attributes_tags = array_keys($this->operation_tags);
512
+		$job_attributes_tags = array_keys($this->job_tags);
513
+		$printer_attributes_tags = array_keys($this->printer_tags);
514
+		self::unsetAttribute($attribute);
515
+		if (in_array($attribute, $operation_attributes_tags))
516
+		{
517
+			if (!is_array($values))
518
+			{
519
+				self::_setOperationAttribute($attribute, $values);
520
+			}
521
+			else
522
+			{
523
+				foreach($values as $value)
524
+				{
525
+					self::_setOperationAttribute($attribute, $value);
526
+				}
527
+			}
528
+		}
529
+		elseif (in_array($attribute, $job_attributes_tags))
530
+		{
531
+			if (!is_array($values))
532
+			{
533
+				self::_setJobAttribute($attribute, $values);
534
+			}
535
+			else
536
+			{
537
+				foreach($values as $value)
538
+				{
539
+					self::_setJobAttribute($attribute, $value);
540
+				}
541
+			}
542
+		}
543
+		elseif (in_array($attribute, $printer_attributes_tags))
544
+		{
545
+			if (!is_array($values))
546
+			{
547
+				self::_setPrinterAttribute($attribute, $values);
548
+			}
549
+			else
550
+			{
551
+				foreach($values as $value)
552
+				{
553
+					self::_setPrinterAttribute($attribute, $value);
554
+				}
555
+			}
556
+		}
557
+		else
558
+		{
559
+			trigger_error(
560
+				sprintf(_('SetAttribute: Tag "%s" is not a printer or a job attribute'),
561
+					$attribute) , E_USER_NOTICE);
562
+			self::_putDebug(
563
+				sprintf(_('SetAttribute: Tag "%s" is not a printer or a job attribute'),
564
+					$attribute) , 3);
565
+			self::_errorLog(
566
+				sprintf(_('SetAttribute: Tag "%s" is not a printer or a job attribute'),
567
+					$attribute) , 2);
568
+			return FALSE;
569
+		}
570
+	}
571
+
572
+	public function unsetAttribute($attribute)
573
+	{
574
+		$operation_attributes_tags = array_keys($this->operation_tags);
575
+		$job_attributes_tags = array_keys($this->job_tags);
576
+		$printer_attributes_tags = array_keys($this->printer_tags);
577
+		if (in_array($attribute, $operation_attributes_tags))
578
+		{
579
+			unset(
580
+				$this->operation_tags[$attribute]['value'],
581
+				$this->operation_tags[$attribute]['systag']
582
+			);
583
+		}
584
+		elseif (in_array($attribute, $job_attributes_tags))
585
+		{
586
+			unset(
587
+				$this->job_tags[$attribute]['value'],
588
+				$this->job_tags[$attribute]['systag']
589
+			);
590
+		}
591
+		elseif (in_array($attribute, $printer_attributes_tags))
592
+		{
593
+			unset(
594
+				$this->printer_tags[$attribute]['value'],
595
+				$this->printer_tags[$attribute]['systag']
596
+			);
597
+		}
598
+		else
599
+		{
600
+			trigger_error(
601
+				sprintf(_('unsetAttribute: Tag "%s" is not a printer or a job attribute'),
602
+					$attribute) , E_USER_NOTICE);
603
+			self::_putDebug(
604
+				sprintf(_('unsetAttribute: Tag "%s" is not a printer or a job attribute'),
605
+					$attribute) , 3);
606
+			self::_errorLog(
607
+				sprintf(_('unsetAttribute: Tag "%s" is not a printer or a job attribute'),
608
+					$attribute) , 2);
609
+			return FALSE;
610
+		}
611
+		return true;
612
+	}
613
+
614
+	//
615
+	// LOGGING / DEBUGGING
616
+	//
617
+	/**
618
+	 * Sets log file destination. Creates the file if has permission.
619
+	 *
620
+	 * @param string $log_destination
621
+	 * @param string $destination_type
622
+	 * @param int $level
623
+	 *
624
+	 * @throws ippException
625
+	 */
626
+	public function setLog($log_destination, $destination_type = 'file', $level = 2)
627
+	{
628
+		if (!file_exists($log_destination) && is_writable(dirname($log_destination)))
629
+		{
630
+			touch($log_destination);
631
+			chmod($log_destination, 0777);
632
+		}
633
+
634
+		switch ($destination_type)
635
+		{
636
+			case 'file':
637
+			case 3:
638
+				$this->log_destination = $log_destination;
639
+				$this->log_type = 3;
640
+				break;
641
+
642
+			case 'logger':
643
+			case 0:
644
+				$this->log_destination = '';
645
+				$this->log_type = 0;
646
+				break;
647
+
648
+			case 'e-mail':
649
+			case 1:
650
+				$this->log_destination = $log_destination;
651
+				$this->log_type = 1;
652
+				break;
653
+		}
654
+		$this->log_level = $level;
655
+	}
656
+
657
+	public function printDebug()
658
+	{
659
+		for ($i = 0; $i < $this->debug_count; $i++)
660
+		{
661
+			echo $this->debug[$i], "\n";
662
+		}
663
+		$this->debug = array();
664
+		$this->debug_count = 0;
665
+	}
666
+
667
+	public function getDebug()
668
+	{
669
+		$debug = '';
670
+		for ($i = 0; $i < $this->debug_count; $i++)
671
+		{
672
+			$debug.= $this->debug[$i];
673
+		}
674
+		$this->debug = array();
675
+		$this->debug_count = 0;
676
+		return $debug;
677
+	}
678
+
679
+	//
680
+	// OPERATIONS
681
+	//
682
+	public function printJob()
683
+	{
684
+		// this BASIC version of printJob do not parse server
685
+		// output for job's attributes
686
+		self::_putDebug(
687
+			sprintf(
688
+				"************** Date: %s ***********",
689
+				date('Y-m-d H:i:s')
690
+			)
691
+		);
692
+		if (!$this->_stringJob()) {
693
+			return FALSE;
694
+		}
695
+		if (is_readable($this->data))
696
+		{
697
+			self::_putDebug(_("Printing a FILE"));
698
+			$this->output = $this->stringjob;
699
+			if ($this->setup->datatype == "TEXT")
700
+			{
701
+				$this->output.= chr(0x16);
702
+			}
703
+			$post_values = array(
704
+				"Content-Type" => "application/ipp",
705
+				"Data" => $this->output,
706
+				"File" => $this->data
707
+			);
708
+			if ($this->setup->datatype == "TEXT" && !isset($this->setup->noFormFeed))
709
+			{
710
+				$post_values = array_merge(
711
+					$post_values,
712
+					array(
713
+						"Filetype" => "TEXT"
714
+					)
715
+				);
716
+			}
717
+		}
718
+		else
719
+		{
720
+			self::_putDebug(_("Printing DATA"));
721
+			$this->output =
722
+				$this->stringjob
723
+					. $this->datahead
724
+					. $this->data
725
+					. $this->datatail;
726
+			$post_values = array(
727
+				"Content-Type" => "application/ipp",
728
+				"Data" => $this->output
729
+			);
730
+		}
731
+		if (self::_sendHttp($post_values, $this->paths["printers"]))
732
+		{
733
+			self::_parseServerOutput();
734
+		}
735
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
736
+		{
737
+			$this->status = array_merge($this->status, array(
738
+				$this->serveroutput->status
739
+			));
740
+			if ($this->serveroutput->status == "successfull-ok")
741
+			{
742
+				self::_errorLog(
743
+					sprintf("printing job %s: ", $this->last_job)
744
+						. $this->serveroutput->status,
745
+					3);
746
+			}
747
+			else
748
+			{
749
+				self::_errorLog(
750
+					sprintf("printing job: ", $this->last_job)
751
+						. $this->serveroutput->status,
752
+					1);
753
+			}
754
+				return $this->serveroutput->status;
755
+		}
756
+
757
+	$this->status =
758
+		array_merge($this->status, array("OPERATION FAILED"));
759
+		$this->jobs =
760
+			array_merge($this->jobs, array(""));
761
+		$this->jobs_uri =
762
+			array_merge($this->jobs_uri, array(""));
763
+
764
+		self::_errorLog("printing job : OPERATION FAILED", 1);
765
+		return false;
766
+	}
767
+
768
+	//
769
+	// HTTP OUTPUT
770
+	//
771
+	protected function _sendHttp($post_values, $uri)
772
+	{
773
+		/*
774 774
             This function Copyright (C) 2005-2006 Thomas Harding, Manuel Lemos
775 775
         */
776
-        $this->response_completed[] = "no";
777
-        unset($this->serverouptut);
778
-        self::_putDebug(_("Processing HTTP request") , 2);
779
-        $this->serveroutput->headers = array();
780
-        $this->serveroutput->body = "";
781
-        $http = new http_class;
782
-        if (!$this->unix) {
783
-        	// DOL_LDR_CHANGE
784
-        	if (empty($this->host)) $this->host='127.0.0.1';
785
-            $http->host = $this->host;
786
-        }
787
-        else {
788
-            $http->host = "localhost";
789
-        }
790
-        $http->with_exceptions = $this->with_exceptions;
791
-        if ($this->debug_http)
792
-        {
793
-            $http->debug = 1;
794
-            $http->html_debug = 0;
795
-        }
796
-        else
797
-        {
798
-            $http->debug = 0;
799
-            $http->html_debug = 0;
800
-        }
801
-        $url = "http://" . $this->host;
802
-        if ($this->ssl) {
803
-            $url = "https://" . $this->host;
804
-        }
805
-        if ($this->unix) {
806
-            $url = "unix://" . $this->host;
807
-        }
808
-        $http->port = $this->port;
809
-        $http->timeout = $this->http_timeout;
810
-        $http->data_timeout = $this->http_data_timeout;
811
-        $http->force_multipart_form_post = false;
812
-        $http->user = $this->username;
813
-        $http->password = $this->password;
814
-        $error = $http->GetRequestArguments($url, $arguments);
815
-        $arguments["RequestMethod"] = "POST";
816
-        $arguments["Headers"] = array(
817
-            "Content-Type" => "application/ipp"
818
-        );
819
-        $arguments["BodyStream"] = array(
820
-            array(
821
-                "Data" => $post_values["Data"]
822
-            )
823
-        );
824
-        if (isset($post_values["File"])) {
825
-            $arguments["BodyStream"][] = array(
826
-                "File" => $post_values["File"]
827
-            );
828
-        }
829
-        if (isset($post_values["FileType"])
830
-            && !strcmp($post_values["FileType"], "TEXT")
831
-        )
832
-        {
833
-            $arguments["BodyStream"][] = array("Data" => Chr(12));
834
-        }
835
-        $arguments["RequestURI"] = $uri;
836
-        if ($this->with_exceptions && $this->handle_http_exceptions)
837
-        {
838
-            try
839
-            {
840
-                $success = $http->Open($arguments);
841
-            }
842
-            catch(httpException $e)
843
-            {
844
-                throw new ippException(
845
-                    sprintf("http error: %s", $e->getMessage()),
846
-                        $e->getErrno());
847
-            }
848
-        }
849
-        else
850
-        {
851
-        	$success = $http->Open($arguments);
852
-        }
853
-        if ($success[0] == true)
854
-        {
855
-            $success = $http->SendRequest($arguments);
856
-            if ($success[0] == true)
857
-            {
858
-                self::_putDebug("H T T P    R E Q U E S T :");
859
-                self::_putDebug("Request headers:");
860
-                for (Reset($http->request_headers) , $header = 0; $header < count($http->request_headers); Next($http->request_headers) , $header++)
861
-                {
862
-                    $header_name = Key($http->request_headers);
863
-                    if (GetType($http->request_headers[$header_name]) == "array")
864
-                    {
865
-                        for ($header_value = 0; $header_value < count($http->request_headers[$header_name]); $header_value++)
866
-                        {
867
-                            self::_putDebug($header_name . ": " . $http->request_headers[$header_name][$header_value]);
868
-                        }
869
-                    }
870
-                    else
871
-                    {
872
-                        self::_putDebug($header_name . ": " . $http->request_headers[$header_name]);
873
-                    }
874
-                }
875
-                self::_putDebug("Request body:");
876
-                self::_putDebug(
877
-                    htmlspecialchars($http->request_body)
878
-                        . "*********** END REQUEST BODY *********"
879
-                );
880
-                $i = 0;
881
-                $headers = array();
882
-                unset($this->serveroutput->headers);
883
-                $http->ReadReplyHeaders($headers);
884
-                self::_putDebug("H T T P    R E S P O N S E :");
885
-                self::_putDebug("Response headers:");
886
-                for (Reset($headers) , $header = 0; $header < count($headers); Next($headers) , $header++)
887
-                {
888
-                    $header_name = Key($headers);
889
-                    if (GetType($headers[$header_name]) == "array")
890
-                    {
891
-                        for ($header_value = 0; $header_value < count($headers[$header_name]); $header_value++)
892
-                        {
893
-                            self::_putDebug($header_name . ": " . $headers[$header_name][$header_value]);
894
-                            $this->serveroutput->headers[$i] =
895
-                                $header_name . ": "
896
-                                    . $headers[$header_name][$header_value];
897
-                            $i++;
898
-                        }
899
-                    }
900
-                    else
901
-                    {
902
-                        self::_putDebug($header_name . ": " . $headers[$header_name]);
903
-                        $this->serveroutput->headers[$i] =
904
-                            $header_name
905
-                                . ": "
906
-                                . $headers[$header_name];
907
-                        $i++;
908
-                    }
909
-                }
910
-                self::_putDebug("\n\nResponse body:\n");
911
-                $this->serveroutput->body = "";
912
-                for (;;)
913
-                {
914
-                    $http->ReadReplyBody($body, 1024);
915
-                    if (strlen($body) == 0) {
916
-                        break;
917
-                    }
918
-
919
-                    self::_putDebug(htmlentities($body));
920
-                    $this->serveroutput->body.= $body;
921
-                }
922
-                self::_putDebug("********* END RESPONSE BODY ********");
923
-            }
924
-        }
925
-        $http->Close();
926
-        return true;
927
-    }
928
-
929
-    //
930
-    // INIT
931
-    //
932
-    protected function _initTags()
933
-    {
934
-        $this->tags_types = array(
935
-            "unsupported" => array(
936
-                "tag" => chr(0x10) ,
937
-                "build" => ""
938
-            ) ,
939
-            "reserved" => array(
940
-                "tag" => chr(0x11) ,
941
-                "build" => ""
942
-            ) ,
943
-            "unknown" => array(
944
-                "tag" => chr(0x12) ,
945
-                "build" => ""
946
-            ) ,
947
-            "no-value" => array(
948
-                "tag" => chr(0x13) ,
949
-                "build" => "no_value"
950
-            ) ,
951
-            "integer" => array(
952
-                "tag" => chr(0x21) ,
953
-                "build" => "integer"
954
-            ) ,
955
-            "boolean" => array(
956
-                "tag" => chr(0x22) ,
957
-                "build" => "boolean"
958
-            ) ,
959
-            "enum" => array(
960
-                "tag" => chr(0x23) ,
961
-                "build" => "enum"
962
-            ) ,
963
-            "octetString" => array(
964
-                "tag" => chr(0x30) ,
965
-                "build" => "octet_string"
966
-            ) ,
967
-            "datetime" => array(
968
-                "tag" => chr(0x31) ,
969
-                "build" => "datetime"
970
-            ) ,
971
-            "resolution" => array(
972
-                "tag" => chr(0x32) ,
973
-                "build" => "resolution"
974
-            ) ,
975
-            "rangeOfInteger" => array(
976
-                "tag" => chr(0x33) ,
977
-                "build" => "range_of_integers"
978
-            ) ,
979
-            "textWithLanguage" => array(
980
-                "tag" => chr(0x35) ,
981
-                "build" => "string"
982
-            ) ,
983
-            "nameWithLanguage" => array(
984
-                "tag" => chr(0x36) ,
985
-                "build" => "string"
986
-            ) ,
987
-            /*
776
+		$this->response_completed[] = "no";
777
+		unset($this->serverouptut);
778
+		self::_putDebug(_("Processing HTTP request") , 2);
779
+		$this->serveroutput->headers = array();
780
+		$this->serveroutput->body = "";
781
+		$http = new http_class;
782
+		if (!$this->unix) {
783
+			// DOL_LDR_CHANGE
784
+			if (empty($this->host)) $this->host='127.0.0.1';
785
+			$http->host = $this->host;
786
+		}
787
+		else {
788
+			$http->host = "localhost";
789
+		}
790
+		$http->with_exceptions = $this->with_exceptions;
791
+		if ($this->debug_http)
792
+		{
793
+			$http->debug = 1;
794
+			$http->html_debug = 0;
795
+		}
796
+		else
797
+		{
798
+			$http->debug = 0;
799
+			$http->html_debug = 0;
800
+		}
801
+		$url = "http://" . $this->host;
802
+		if ($this->ssl) {
803
+			$url = "https://" . $this->host;
804
+		}
805
+		if ($this->unix) {
806
+			$url = "unix://" . $this->host;
807
+		}
808
+		$http->port = $this->port;
809
+		$http->timeout = $this->http_timeout;
810
+		$http->data_timeout = $this->http_data_timeout;
811
+		$http->force_multipart_form_post = false;
812
+		$http->user = $this->username;
813
+		$http->password = $this->password;
814
+		$error = $http->GetRequestArguments($url, $arguments);
815
+		$arguments["RequestMethod"] = "POST";
816
+		$arguments["Headers"] = array(
817
+			"Content-Type" => "application/ipp"
818
+		);
819
+		$arguments["BodyStream"] = array(
820
+			array(
821
+				"Data" => $post_values["Data"]
822
+			)
823
+		);
824
+		if (isset($post_values["File"])) {
825
+			$arguments["BodyStream"][] = array(
826
+				"File" => $post_values["File"]
827
+			);
828
+		}
829
+		if (isset($post_values["FileType"])
830
+			&& !strcmp($post_values["FileType"], "TEXT")
831
+		)
832
+		{
833
+			$arguments["BodyStream"][] = array("Data" => Chr(12));
834
+		}
835
+		$arguments["RequestURI"] = $uri;
836
+		if ($this->with_exceptions && $this->handle_http_exceptions)
837
+		{
838
+			try
839
+			{
840
+				$success = $http->Open($arguments);
841
+			}
842
+			catch(httpException $e)
843
+			{
844
+				throw new ippException(
845
+					sprintf("http error: %s", $e->getMessage()),
846
+						$e->getErrno());
847
+			}
848
+		}
849
+		else
850
+		{
851
+			$success = $http->Open($arguments);
852
+		}
853
+		if ($success[0] == true)
854
+		{
855
+			$success = $http->SendRequest($arguments);
856
+			if ($success[0] == true)
857
+			{
858
+				self::_putDebug("H T T P    R E Q U E S T :");
859
+				self::_putDebug("Request headers:");
860
+				for (Reset($http->request_headers) , $header = 0; $header < count($http->request_headers); Next($http->request_headers) , $header++)
861
+				{
862
+					$header_name = Key($http->request_headers);
863
+					if (GetType($http->request_headers[$header_name]) == "array")
864
+					{
865
+						for ($header_value = 0; $header_value < count($http->request_headers[$header_name]); $header_value++)
866
+						{
867
+							self::_putDebug($header_name . ": " . $http->request_headers[$header_name][$header_value]);
868
+						}
869
+					}
870
+					else
871
+					{
872
+						self::_putDebug($header_name . ": " . $http->request_headers[$header_name]);
873
+					}
874
+				}
875
+				self::_putDebug("Request body:");
876
+				self::_putDebug(
877
+					htmlspecialchars($http->request_body)
878
+						. "*********** END REQUEST BODY *********"
879
+				);
880
+				$i = 0;
881
+				$headers = array();
882
+				unset($this->serveroutput->headers);
883
+				$http->ReadReplyHeaders($headers);
884
+				self::_putDebug("H T T P    R E S P O N S E :");
885
+				self::_putDebug("Response headers:");
886
+				for (Reset($headers) , $header = 0; $header < count($headers); Next($headers) , $header++)
887
+				{
888
+					$header_name = Key($headers);
889
+					if (GetType($headers[$header_name]) == "array")
890
+					{
891
+						for ($header_value = 0; $header_value < count($headers[$header_name]); $header_value++)
892
+						{
893
+							self::_putDebug($header_name . ": " . $headers[$header_name][$header_value]);
894
+							$this->serveroutput->headers[$i] =
895
+								$header_name . ": "
896
+									. $headers[$header_name][$header_value];
897
+							$i++;
898
+						}
899
+					}
900
+					else
901
+					{
902
+						self::_putDebug($header_name . ": " . $headers[$header_name]);
903
+						$this->serveroutput->headers[$i] =
904
+							$header_name
905
+								. ": "
906
+								. $headers[$header_name];
907
+						$i++;
908
+					}
909
+				}
910
+				self::_putDebug("\n\nResponse body:\n");
911
+				$this->serveroutput->body = "";
912
+				for (;;)
913
+				{
914
+					$http->ReadReplyBody($body, 1024);
915
+					if (strlen($body) == 0) {
916
+						break;
917
+					}
918
+
919
+					self::_putDebug(htmlentities($body));
920
+					$this->serveroutput->body.= $body;
921
+				}
922
+				self::_putDebug("********* END RESPONSE BODY ********");
923
+			}
924
+		}
925
+		$http->Close();
926
+		return true;
927
+	}
928
+
929
+	//
930
+	// INIT
931
+	//
932
+	protected function _initTags()
933
+	{
934
+		$this->tags_types = array(
935
+			"unsupported" => array(
936
+				"tag" => chr(0x10) ,
937
+				"build" => ""
938
+			) ,
939
+			"reserved" => array(
940
+				"tag" => chr(0x11) ,
941
+				"build" => ""
942
+			) ,
943
+			"unknown" => array(
944
+				"tag" => chr(0x12) ,
945
+				"build" => ""
946
+			) ,
947
+			"no-value" => array(
948
+				"tag" => chr(0x13) ,
949
+				"build" => "no_value"
950
+			) ,
951
+			"integer" => array(
952
+				"tag" => chr(0x21) ,
953
+				"build" => "integer"
954
+			) ,
955
+			"boolean" => array(
956
+				"tag" => chr(0x22) ,
957
+				"build" => "boolean"
958
+			) ,
959
+			"enum" => array(
960
+				"tag" => chr(0x23) ,
961
+				"build" => "enum"
962
+			) ,
963
+			"octetString" => array(
964
+				"tag" => chr(0x30) ,
965
+				"build" => "octet_string"
966
+			) ,
967
+			"datetime" => array(
968
+				"tag" => chr(0x31) ,
969
+				"build" => "datetime"
970
+			) ,
971
+			"resolution" => array(
972
+				"tag" => chr(0x32) ,
973
+				"build" => "resolution"
974
+			) ,
975
+			"rangeOfInteger" => array(
976
+				"tag" => chr(0x33) ,
977
+				"build" => "range_of_integers"
978
+			) ,
979
+			"textWithLanguage" => array(
980
+				"tag" => chr(0x35) ,
981
+				"build" => "string"
982
+			) ,
983
+			"nameWithLanguage" => array(
984
+				"tag" => chr(0x36) ,
985
+				"build" => "string"
986
+			) ,
987
+			/*
988 988
             "text" => array ("tag" => chr(0x40),
989 989
             "build" => "string"),
990 990
             "text string" => array ("tag" => chr(0x40),
991 991
             "build" => "string"),
992 992
             */
993
-            "textWithoutLanguage" => array(
994
-                "tag" => chr(0x41) ,
995
-                "build" => "string"
996
-            ) ,
997
-            "nameWithoutLanguage" => array(
998
-                "tag" => chr(0x42) ,
999
-                "buid" => "string"
1000
-            ) ,
1001
-            "keyword" => array(
1002
-                "tag" => chr(0x44) ,
1003
-                "build" => "string"
1004
-            ) ,
1005
-            "uri" => array(
1006
-                "tag" => chr(0x45) ,
1007
-                "build" => "string"
1008
-            ) ,
1009
-            "uriScheme" => array(
1010
-                "tag" => chr(0x46) ,
1011
-                "build" => "string"
1012
-            ) ,
1013
-            "charset" => array(
1014
-                "tag" => chr(0x47) ,
1015
-                "build" => "string"
1016
-            ) ,
1017
-            "naturalLanguage" => array(
1018
-                "tag" => chr(0x48) ,
1019
-                "build" => "string"
1020
-            ) ,
1021
-            "mimeMediaType" => array(
1022
-                "tag" => chr(0x49) ,
1023
-                "build" => "string"
1024
-            ) ,
1025
-            "extendedAttributes" => array(
1026
-                "tag" => chr(0x7F) ,
1027
-                "build" => "extended"
1028
-            ) ,
1029
-        );
1030
-        $this->operation_tags = array(
1031
-            "compression" => array(
1032
-                "tag" => "keyword"
1033
-            ) ,
1034
-            "document-natural-language" => array(
1035
-                "tag" => "naturalLanguage"
1036
-            ) ,
1037
-            "job-k-octets" => array(
1038
-                "tag" => "integer"
1039
-            ) ,
1040
-            "job-impressions" => array(
1041
-                "tag" => "integer"
1042
-            ) ,
1043
-            "job-media-sheets" => array(
1044
-                "tag" => "integer"
1045
-            ) ,
1046
-        );
1047
-        $this->job_tags = array(
1048
-            "job-priority" => array(
1049
-                "tag" => "integer"
1050
-            ) ,
1051
-            "job-hold-until" => array(
1052
-                "tag" => "keyword"
1053
-            ) ,
1054
-            "job-sheets" => array(
1055
-                "tag" => "keyword"
1056
-            ) , //banner page
1057
-            "multiple-document-handling" => array(
1058
-                "tag" => "keyword"
1059
-            ) ,
1060
-            //"copies" => array("tag" => "integer"),
1061
-            "finishings" => array(
1062
-                "tag" => "enum"
1063
-            ) ,
1064
-            //"page-ranges" => array("tag" => "rangeOfInteger"), // has its own function
1065
-            //"sides" => array("tag" => "keyword"), // has its own function
1066
-            "number-up" => array(
1067
-                "tag" => "integer"
1068
-            ) ,
1069
-            "orientation-requested" => array(
1070
-                "tag" => "enum"
1071
-            ) ,
1072
-            "media" => array(
1073
-                "tag" => "keyword"
1074
-            ) ,
1075
-            "printer-resolution" => array(
1076
-                "tag" => "resolution"
1077
-            ) ,
1078
-            "print-quality" => array(
1079
-                "tag" => "enum"
1080
-            ) ,
1081
-            "job-message-from-operator" => array(
1082
-                "tag" => "textWithoutLanguage"
1083
-            ) ,
1084
-        );
1085
-        $this->printer_tags = array(
1086
-            "requested-attributes" => array(
1087
-                "tag" => "keyword"
1088
-            )
1089
-        );
1090
-    }
1091
-
1092
-    //
1093
-    // SETUP
1094
-    //
1095
-    protected function _setOperationId()
1096
-    {
1097
-        $prepend = '';
1098
-        $this->operation_id+= 1;
1099
-        $this->meta->operation_id = self::_integerBuild($this->operation_id);
1100
-        self::_putDebug("operation id is: " . $this->operation_id, 2);
1101
-    }
1102
-
1103
-    protected function _setJobId()
1104
-    {
1105
-        $this->meta->jobid+= 1;
1106
-        $prepend = '';
1107
-        $prepend_length = 4 - strlen($this->meta->jobid);
1108
-        for ($i = 0; $i < $prepend_length; $i++) {
1109
-            $prepend.= '0';
1110
-        }
1111
-        return $prepend . $this->meta->jobid;
1112
-    }
1113
-
1114
-    protected function _setJobUri($job_uri)
1115
-    {
1116
-        $this->meta->job_uri = chr(0x45) // type uri
1117
-            . chr(0x00) . chr(0x07) // name-length
1118
-            . "job-uri"
1119
-            //. chr(0x00).chr(strlen($job_uri))
1120
-            . self::_giveMeStringLength($job_uri) . $job_uri;
1121
-        self::_putDebug("job-uri is: " . $job_uri, 2);
1122
-    }
1123
-
1124
-    //
1125
-    // RESPONSE PARSING
1126
-    //
1127
-    protected function _parseServerOutput()
1128
-    {
1129
-        $this->serveroutput->response = array();
1130
-        if (!self::_parseHttpHeaders()) {
1131
-            return FALSE;
1132
-        }
1133
-        $this->_parsing->offset = 0;
1134
-        self::_parseIppVersion();
1135
-        self::_parseStatusCode();
1136
-        self::_parseRequestID();
1137
-        $this->_parseResponse();
1138
-        //devel
1139
-        self::_putDebug(
1140
-            sprintf("***** IPP STATUS: %s ******", $this->serveroutput->status),
1141
-            4);
1142
-        self::_putDebug("****** END OF OPERATION ****");
1143
-        return true;
1144
-    }
1145
-
1146
-    protected function _parseHttpHeaders()
1147
-    {
1148
-        $response = "";
1149
-        switch ($this->serveroutput->headers[0])
1150
-        {
1151
-            case "http/1.1 200 ok: ":
1152
-                $this->serveroutput->httpstatus = "HTTP/1.1 200 OK";
1153
-                $response = "OK";
1154
-                break;
1155
-
1156
-            // primitive http/1.0 for Lexmark printers (from Rick Baril)
1157
-            case "http/1.0 200 ok: ":
1158
-                $this->serveroutput->httpstatus = "HTTP/1.0 200 OK";
1159
-                $response = "OK";
1160
-                break;
1161
-
1162
-            case "http/1.1 100 continue: ":
1163
-                $this->serveroutput->httpstatus = "HTTP/1.1 100 CONTINUE";
1164
-                $response = "OK";
1165
-                break;
1166
-
1167
-            case "":
1168
-                $this->serveroutput->httpstatus = "HTTP/1.1 000 No Response From Server";
1169
-                $this->serveroutput->status = "HTTP-ERROR-000_NO_RESPONSE_FROM_SERVER";
1170
-                trigger_error("No Response From Server", E_USER_WARNING);
1171
-                self::_errorLog("No Response From Server", 1);
1172
-                $this->disconnected = 1;
1173
-                return FALSE;
1174
-                break;
1175
-
1176
-            default:
1177
-                $server_response = preg_replace("/: $/", '', $this->serveroutput->headers[0]);
1178
-                #$strings = split(' ', $server_response, 3);
1179
-                $strings = preg_split('# #', $server_response, 3);
1180
-                $errno = $strings[1];
1181
-                $string = strtoupper(str_replace(' ', '_', $strings[2]));
1182
-                trigger_error(
1183
-                    sprintf(_("server responds %s") , $server_response),
1184
-                    E_USER_WARNING);
1185
-                self::_errorLog("server responds " . $server_response, 1);
1186
-                $this->serveroutput->httpstatus =
1187
-                    strtoupper($strings[0])
1188
-                        . " "
1189
-                        . $errno
1190
-                        . " "
1191
-                        . ucfirst($strings[2]);
1192
-
1193
-                $this->serveroutput->status =
1194
-                    "HTTP-ERROR-"
1195
-                        . $errno
1196
-                        . "-"
1197
-                        . $string;
1198
-                $this->disconnected = 1;
1199
-                return FALSE;
1200
-                break;
1201
-        }
1202
-        unset($this->serveroutput->headers);
1203
-        return TRUE;
1204
-    }
1205
-
1206
-    protected function _parseIppVersion()
1207
-    {
1208
-        $ippversion =
1209
-            (ord($this->serveroutput->body[$this->_parsing->offset]) * 256)
1210
-                + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1211
-        switch ($ippversion)
1212
-        {
1213
-            case 0x0101:
1214
-                $this->serveroutput->ipp_version = "1.1";
1215
-                break;
1216
-
1217
-            default:
1218
-                $this->serveroutput->ipp_version =
1219
-                    sprintf("%u.%u (Unknown)",
1220
-                        ord($this->serveroutput->body[$this->_parsing->offset]) * 256,
1221
-                        ord($this->serveroutput->body[$this->_parsing->offset + 1]));
1222
-                break;
1223
-        }
1224
-        self::_putDebug("I P P    R E S P O N S E :\n\n");
1225
-        self::_putDebug(
1226
-            sprintf("IPP version %s%s: %s",
1227
-                ord($this->serveroutput->body[$this->_parsing->offset]),
1228
-                ord($this->serveroutput->body[$this->_parsing->offset + 1]),
1229
-                $this->serveroutput->ipp_version));
1230
-        $this->_parsing->offset+= 2;
1231
-        return;
1232
-    }
1233
-
1234
-    protected function _parseStatusCode()
1235
-    {
1236
-        $status_code =
1237
-            (ord($this->serveroutput->body[$this->_parsing->offset]) * 256)
1238
-            + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1239
-        $this->serveroutput->status = "NOT PARSED";
1240
-        $this->_parsing->offset+= 2;
1241
-        if (strlen($this->serveroutput->body) < $this->_parsing->offset)
1242
-        {
1243
-            return false;
1244
-        }
1245
-        if ($status_code < 0x00FF)
1246
-        {
1247
-            $this->serveroutput->status = "successfull";
1248
-        }
1249
-        elseif ($status_code < 0x01FF)
1250
-        {
1251
-            $this->serveroutput->status = "informational";
1252
-        }
1253
-        elseif ($status_code < 0x02FF)
1254
-        {
1255
-            $this->serveroutput->status = "redirection";
1256
-        }
1257
-        elseif ($status_code < 0x04FF)
1258
-        {
1259
-            $this->serveroutput->status = "client-error";
1260
-        }
1261
-        elseif ($status_code < 0x05FF)
1262
-        {
1263
-            $this->serveroutput->status = "server-error";
1264
-        }
1265
-        switch ($status_code)
1266
-        {
1267
-            case 0x0000:
1268
-                $this->serveroutput->status = "successfull-ok";
1269
-                break;
1270
-
1271
-            case 0x0001:
1272
-                $this->serveroutput->status = "successful-ok-ignored-or-substituted-attributes";
1273
-                break;
1274
-
1275
-            case 0x002:
1276
-                $this->serveroutput->status = "successful-ok-conflicting-attributes";
1277
-                break;
1278
-
1279
-            case 0x0400:
1280
-                $this->serveroutput->status = "client-error-bad-request";
1281
-                break;
1282
-
1283
-            case 0x0401:
1284
-                $this->serveroutput->status = "client-error-forbidden";
1285
-                break;
1286
-
1287
-            case 0x0402:
1288
-                $this->serveroutput->status = "client-error-not-authenticated";
1289
-                break;
1290
-
1291
-            case 0x0403:
1292
-                $this->serveroutput->status = "client-error-not-authorized";
1293
-                break;
1294
-
1295
-            case 0x0404:
1296
-                $this->serveroutput->status = "client-error-not-possible";
1297
-                break;
1298
-
1299
-            case 0x0405:
1300
-                $this->serveroutput->status = "client-error-timeout";
1301
-                break;
1302
-
1303
-            case 0x0406:
1304
-                $this->serveroutput->status = "client-error-not-found";
1305
-                break;
1306
-
1307
-            case 0x0407:
1308
-                $this->serveroutput->status = "client-error-gone";
1309
-                break;
1310
-
1311
-            case 0x0408:
1312
-                $this->serveroutput->status = "client-error-request-entity-too-large";
1313
-                break;
1314
-
1315
-            case 0x0409:
1316
-                $this->serveroutput->status = "client-error-request-value-too-long";
1317
-                break;
1318
-
1319
-            case 0x040A:
1320
-                $this->serveroutput->status = "client-error-document-format-not-supported";
1321
-                break;
1322
-
1323
-            case 0x040B:
1324
-                $this->serveroutput->status = "client-error-attributes-or-values-not-supported";
1325
-                break;
1326
-
1327
-            case 0x040C:
1328
-                $this->serveroutput->status = "client-error-uri-scheme-not-supported";
1329
-                break;
1330
-
1331
-            case 0x040D:
1332
-                $this->serveroutput->status = "client-error-charset-not-supported";
1333
-                break;
1334
-
1335
-            case 0x040E:
1336
-                $this->serveroutput->status = "client-error-conflicting-attributes";
1337
-                break;
1338
-
1339
-            case 0x040F:
1340
-                $this->serveroutput->status = "client-error-compression-not-supported";
1341
-                break;
1342
-
1343
-            case 0x0410:
1344
-                $this->serveroutput->status = "client-error-compression-error";
1345
-                break;
1346
-
1347
-            case 0x0411:
1348
-                $this->serveroutput->status = "client-error-document-format-error";
1349
-                break;
1350
-
1351
-            case 0x0412:
1352
-                $this->serveroutput->status = "client-error-document-access-error";
1353
-                break;
1354
-
1355
-            case 0x0413: // RFC3380
1356
-                $this->serveroutput->status = "client-error-attributes-not-settable";
1357
-                break;
1358
-
1359
-            case 0x0500:
1360
-                $this->serveroutput->status = "server-error-internal-error";
1361
-                break;
1362
-
1363
-            case 0x0501:
1364
-                $this->serveroutput->status = "server-error-operation-not-supported";
1365
-                break;
1366
-
1367
-            case 0x0502:
1368
-                $this->serveroutput->status = "server-error-service-unavailable";
1369
-                break;
1370
-
1371
-            case 0x0503:
1372
-                $this->serveroutput->status = "server-error-version-not-supported";
1373
-                break;
1374
-
1375
-            case 0x0504:
1376
-                $this->serveroutput->status = "server-error-device-error";
1377
-                break;
1378
-
1379
-            case 0x0505:
1380
-                $this->serveroutput->status = "server-error-temporary-error";
1381
-                break;
1382
-
1383
-            case 0x0506:
1384
-                $this->serveroutput->status = "server-error-not-accepting-jobs";
1385
-                break;
1386
-
1387
-            case 0x0507:
1388
-                $this->serveroutput->status = "server-error-busy";
1389
-                break;
1390
-
1391
-            case 0x0508:
1392
-                $this->serveroutput->status = "server-error-job-canceled";
1393
-                break;
1394
-
1395
-            case 0x0509:
1396
-                $this->serveroutput->status = "server-error-multiple-document-jobs-not-supported";
1397
-                break;
1398
-
1399
-            default:
1400
-                break;
1401
-        }
1402
-        self::_putDebug(
1403
-            sprintf(
1404
-                "status-code: %s%s: %s ",
1405
-                $this->serveroutput->body[$this->_parsing->offset],
1406
-                $this->serveroutput->body[$this->_parsing->offset + 1],
1407
-                $this->serveroutput->status),
1408
-            4);
1409
-        return;
1410
-    }
1411
-
1412
-    protected function _parseRequestID()
1413
-    {
1414
-        $this->serveroutput->request_id =
1415
-            self::_interpretInteger(
1416
-                substr($this->serveroutput->body, $this->_parsing->offset, 4)
1417
-            );
1418
-        self::_putDebug("request-id " . $this->serveroutput->request_id, 2);
1419
-        $this->_parsing->offset+= 4;
1420
-        return;
1421
-    }
1422
-
1423
-    protected function _interpretInteger($value)
1424
-    {
1425
-        // they are _signed_ integers
1426
-        $value_parsed = 0;
1427
-        for ($i = strlen($value); $i > 0; $i --)
1428
-        {
1429
-            $value_parsed +=
1430
-                (
1431
-                    (1 << (($i - 1) * 8))
1432
-                        *
1433
-                        ord($value[strlen($value) - $i])
1434
-                );
1435
-        }
1436
-        if ($value_parsed >= 2147483648)
1437
-        {
1438
-            $value_parsed -= 4294967296;
1439
-        }
1440
-        return $value_parsed;
1441
-    }
1442
-
1443
-    protected function _parseResponse()
1444
-    {
1445
-    }
1446
-
1447
-    //
1448
-    // REQUEST BUILDING
1449
-    //
1450
-    protected function _stringJob()
1451
-    {
1452
-        if (!isset($this->setup->charset)) {
1453
-            self::setCharset();
1454
-        }
1455
-        if (!isset($this->setup->datatype)) {
1456
-            self::setBinary();
1457
-        }
1458
-        if (!isset($this->setup->uri))
1459
-        {
1460
-            $this->getPrinters();
1461
-            unset($this->jobs[count($this->jobs) - 1]);
1462
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
1463
-            unset($this->status[count($this->status) - 1]);
1464
-            if (array_key_exists(0, $this->available_printers))
1465
-            {
1466
-                self::setPrinterURI($this->available_printers[0]);
1467
-            }
1468
-            else
1469
-            {
1470
-                trigger_error(
1471
-                    _("_stringJob: Printer URI is not set: die"),
1472
-                    E_USER_WARNING);
1473
-                self::_putDebug(_("_stringJob: Printer URI is not set: die") , 4);
1474
-                self::_errorLog(" Printer URI is not set, die", 2);
1475
-                return FALSE;
1476
-            }
1477
-        }
1478
-        if (!isset($this->setup->copies)) {
1479
-            self::setCopies(1);
1480
-        }
1481
-        if (!isset($this->setup->language)) {
1482
-            self::setLanguage('en_us');
1483
-        }
1484
-        if (!isset($this->setup->mime_media_type)) {
1485
-            self::setMimeMediaType();
1486
-        }
1487
-        if (!isset($this->setup->jobname)) {
1488
-            self::setJobName();
1489
-        }
1490
-        unset($this->setup->jobname);
1491
-        if (!isset($this->meta->username)) {
1492
-            self::setUserName();
1493
-        }
1494
-        if (!isset($this->meta->fidelity)) {
1495
-            $this->meta->fidelity = '';
1496
-        }
1497
-        if (!isset($this->meta->document_name)) {
1498
-            $this->meta->document_name = '';
1499
-        }
1500
-        if (!isset($this->meta->sides)) {
1501
-            $this->meta->sides = '';
1502
-        }
1503
-        if (!isset($this->meta->page_ranges)) {
1504
-            $this->meta->page_ranges = '';
1505
-        }
1506
-        $jobattributes = '';
1507
-        $operationattributes = '';
1508
-        $printerattributes = '';
1509
-        $this->_buildValues($operationattributes, $jobattributes, $printerattributes);
1510
-        self::_setOperationId();
1511
-        if (!isset($this->error_generation->request_body_malformed))
1512
-        {
1513
-            $this->error_generation->request_body_malformed = "";
1514
-        }
1515
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1516
-            . chr(0x00) . chr(0x02) // Print-Job | operation-id
1517
-            . $this->meta->operation_id //           request-id
1518
-            . chr(0x01) // start operation-attributes | operation-attributes-tag
1519
-            . $this->meta->charset
1520
-            . $this->meta->language
1521
-            . $this->meta->printer_uri
1522
-            . $this->meta->username
1523
-            . $this->meta->jobname
1524
-            . $this->meta->fidelity
1525
-            . $this->meta->document_name
1526
-            . $this->meta->mime_media_type
1527
-            . $operationattributes;
1528
-        if ($this->meta->copies || $this->meta->sides || $this->meta->page_ranges || !empty($jobattributes))
1529
-        {
1530
-            $this->stringjob .=
1531
-                chr(0x02) // start job-attributes | job-attributes-tag
1532
-                    . $this->meta->copies
1533
-                    . $this->meta->sides
1534
-                    . $this->meta->page_ranges
1535
-                    . $jobattributes;
1536
-        }
1537
-        $this->stringjob.= chr(0x03); // end-of-attributes | end-of-attributes-tag
1538
-        self::_putDebug(
1539
-            sprintf(_("String sent to the server is: %s"),
1540
-                $this->stringjob)
1541
-            );
1542
-        return TRUE;
1543
-    }
1544
-
1545
-    protected function _buildValues(&$operationattributes, &$jobattributes, &$printerattributes)
1546
-    {
1547
-        $operationattributes = '';
1548
-        foreach($this->operation_tags as $key => $values)
1549
-        {
1550
-            $item = 0;
1551
-            if (array_key_exists('value', $values))
1552
-            {
1553
-                foreach($values['value'] as $item_value)
1554
-                {
1555
-                    if ($item == 0)
1556
-                    {
1557
-                        $operationattributes .=
1558
-                            $values['systag']
1559
-                                . self::_giveMeStringLength($key)
1560
-                                . $key
1561
-                                . self::_giveMeStringLength($item_value)
1562
-                                . $item_value;
1563
-                    }
1564
-                    else
1565
-                    {
1566
-                        $operationattributes .=
1567
-                            $values['systag']
1568
-                                . self::_giveMeStringLength('')
1569
-                                . self::_giveMeStringLength($item_value)
1570
-                                . $item_value;
1571
-                    }
1572
-                    $item++;
1573
-                }
1574
-            }
1575
-        }
1576
-        $jobattributes = '';
1577
-        foreach($this->job_tags as $key => $values)
1578
-        {
1579
-            $item = 0;
1580
-            if (array_key_exists('value', $values))
1581
-            {
1582
-                foreach($values['value'] as $item_value)
1583
-                {
1584
-                    if ($item == 0)
1585
-                    {
1586
-                        $jobattributes .=
1587
-                            $values['systag']
1588
-                                . self::_giveMeStringLength($key)
1589
-                                . $key
1590
-                                . self::_giveMeStringLength($item_value)
1591
-                                . $item_value;
1592
-                    }
1593
-                    else
1594
-                    {
1595
-                        $jobattributes .=
1596
-                            $values['systag']
1597
-                                . self::_giveMeStringLength('')
1598
-                                . self::_giveMeStringLength($item_value)
1599
-                                . $item_value;
1600
-                    }
1601
-                    $item++;
1602
-                }
1603
-            }
1604
-        }
1605
-        $printerattributes = '';
1606
-        foreach($this->printer_tags as $key => $values)
1607
-        {
1608
-            $item = 0;
1609
-            if (array_key_exists('value', $values))
1610
-            {
1611
-                foreach($values['value'] as $item_value)
1612
-                {
1613
-                    if ($item == 0)
1614
-                    {
1615
-                        $printerattributes .=
1616
-                            $values['systag']
1617
-                                . self::_giveMeStringLength($key)
1618
-                                . $key
1619
-                                . self::_giveMeStringLength($item_value)
1620
-                                . $item_value;
1621
-                    }
1622
-                    else
1623
-                    {
1624
-                        $printerattributes .=
1625
-                            $values['systag']
1626
-                                . self::_giveMeStringLength('')
1627
-                                . self::_giveMeStringLength($item_value)
1628
-                                . $item_value;
1629
-                    }
1630
-                    $item++;
1631
-                }
1632
-            }
1633
-        }
1634
-        reset($this->job_tags);
1635
-        reset($this->operation_tags);
1636
-        reset($this->printer_tags);
1637
-        return true;
1638
-    }
1639
-
1640
-    protected function _giveMeStringLength($string)
1641
-    {
1642
-        $length = strlen($string);
1643
-        if ($length > ((0xFF << 8) + 0xFF)  )
1644
-        {
1645
-            $errmsg = sprintf (
1646
-                _('max string length for an ipp meta-information = %d, while here %d'),
1647
-                ((0xFF << 8) + 0xFF), $length);
1648
-
1649
-            if ($this->with_exceptions)
1650
-            {
1651
-                throw new ippException($errmsg);
1652
-            }
1653
-            else
1654
-            {
1655
-                trigger_error ($errmsg, E_USER_ERROR);
1656
-            }
1657
-        }
1658
-        $int1 = $length & 0xFF;
1659
-        $length -= $int1;
1660
-        $length = $length >> 8;
1661
-        $int2 = $length & 0xFF;
1662
-        return chr($int2) . chr($int1);
1663
-    }
1664
-
1665
-    protected function _enumBuild($tag, $value)
1666
-    {
1667
-        switch ($tag)
1668
-        {
1669
-            case "orientation-requested":
1670
-                switch ($value)
1671
-                {
1672
-                    case 'portrait':
1673
-                        $value = chr(3);
1674
-                        break;
1675
-
1676
-                    case 'landscape':
1677
-                        $value = chr(4);
1678
-                        break;
1679
-
1680
-                    case 'reverse-landscape':
1681
-                        $value = chr(5);
1682
-                        break;
1683
-
1684
-                    case 'reverse-portrait':
1685
-                        $value = chr(6);
1686
-                        break;
1687
-                }
1688
-                break;
1689
-
1690
-            case "print-quality":
1691
-                switch ($value)
1692
-                {
1693
-                    case 'draft':
1694
-                        $value = chr(3);
1695
-                        break;
1696
-
1697
-                    case 'normal':
1698
-                        $value = chr(4);
1699
-                        break;
1700
-
1701
-                    case 'high':
1702
-                        $value = chr(5);
1703
-                        break;
1704
-                }
1705
-                break;
1706
-
1707
-            case "finishing":
1708
-                switch ($value)
1709
-                {
1710
-                    case 'none':
1711
-                        $value = chr(3);
1712
-                        break;
1713
-
1714
-                    case 'staple':
1715
-                        $value = chr(4);
1716
-                        break;
1717
-
1718
-                    case 'punch':
1719
-                        $value = chr(5);
1720
-                        break;
1721
-
1722
-                    case 'cover':
1723
-                        $value = chr(6);
1724
-                        break;
1725
-
1726
-                    case 'bind':
1727
-                        $value = chr(7);
1728
-                        break;
1729
-
1730
-                    case 'saddle-stitch':
1731
-                        $value = chr(8);
1732
-                        break;
1733
-
1734
-                    case 'edge-stitch':
1735
-                        $value = chr(9);
1736
-                        break;
1737
-
1738
-                    case 'staple-top-left':
1739
-                        $value = chr(20);
1740
-                        break;
1741
-
1742
-                    case 'staple-bottom-left':
1743
-                        $value = chr(21);
1744
-                        break;
1745
-
1746
-                    case 'staple-top-right':
1747
-                        $value = chr(22);
1748
-                        break;
1749
-
1750
-                    case 'staple-bottom-right':
1751
-                        $value = chr(23);
1752
-                        break;
1753
-
1754
-                    case 'edge-stitch-left':
1755
-                        $value = chr(24);
1756
-                        break;
1757
-
1758
-                    case 'edge-stitch-top':
1759
-                        $value = chr(25);
1760
-                        break;
1761
-
1762
-                    case 'edge-stitch-right':
1763
-                        $value = chr(26);
1764
-                        break;
1765
-
1766
-                    case 'edge-stitch-bottom':
1767
-                        $value = chr(27);
1768
-                        break;
1769
-
1770
-                    case 'staple-dual-left':
1771
-                        $value = chr(28);
1772
-                        break;
1773
-
1774
-                    case 'staple-dual-top':
1775
-                        $value = chr(29);
1776
-                        break;
1777
-
1778
-                    case 'staple-dual-right':
1779
-                        $value = chr(30);
1780
-                        break;
1781
-
1782
-                    case 'staple-dual-bottom':
1783
-                        $value = chr(31);
1784
-                        break;
1785
-                }
1786
-                break;
1787
-        }
1788
-        $prepend = '';
1789
-        while ((strlen($value) + strlen($prepend)) < 4)
1790
-        {
1791
-            $prepend .= chr(0);
1792
-        }
1793
-        return $prepend . $value;
1794
-    }
1795
-
1796
-    protected function _integerBuild($value)
1797
-    {
1798
-        if ($value >= 2147483647 || $value < - 2147483648)
1799
-        {
1800
-            trigger_error(
1801
-                _("Values must be between -2147483648 and 2147483647: assuming '0'") , E_USER_WARNING);
1802
-            return chr(0x00) . chr(0x00) . chr(0x00) . chr(0x00);
1803
-        }
1804
-        $initial_value = $value;
1805
-        $int1 = $value & 0xFF;
1806
-        $value -= $int1;
1807
-        $value = $value >> 8;
1808
-        $int2 = $value & 0xFF;
1809
-        $value-= $int2;
1810
-        $value = $value >> 8;
1811
-        $int3 = $value & 0xFF;
1812
-        $value-= $int3;
1813
-        $value = $value >> 8;
1814
-        $int4 = $value & 0xFF; //64bits
1815
-        if ($initial_value < 0) {
1816
-            $int4 = chr($int4) | chr(0x80);
1817
-        }
1818
-        else {
1819
-            $int4 = chr($int4);
1820
-        }
1821
-        $value = $int4 . chr($int3) . chr($int2) . chr($int1);
1822
-        return $value;
1823
-    }
1824
-
1825
-    protected function _rangeOfIntegerBuild($integers)
1826
-    {
1827
-        #$integers = split(":", $integers);
1828
-        $integers = preg_split("#:#", $integers);
1829
-        for ($i = 0; $i < 2; $i++) {
1830
-            $outvalue[$i] = self::_integerBuild($integers[$i]);
1831
-        }
1832
-        return $outvalue[0] . $outvalue[1];
1833
-    }
1834
-
1835
-    protected function _setJobAttribute($attribute, $value)
1836
-    {
1837
-        //used by setAttribute
1838
-        $tag_type = $this->job_tags[$attribute]['tag'];
1839
-        switch ($tag_type)
1840
-        {
1841
-            case 'integer':
1842
-                $this->job_tags[$attribute]['value'][] = self::_integerBuild($value);
1843
-                break;
1844
-
1845
-            case 'boolean':
1846
-            case 'nameWithoutLanguage':
1847
-            case 'nameWithLanguage':
1848
-            case 'textWithoutLanguage':
1849
-            case 'textWithLanguage':
1850
-            case 'keyword':
1851
-            case 'naturalLanguage':
1852
-                $this->job_tags[$attribute]['value'][] = $value;
1853
-                break;
1854
-
1855
-            case 'enum':
1856
-                $value = $this->_enumBuild($attribute, $value); // may be overwritten by children
1857
-                $this->job_tags[$attribute]['value'][] = $value;
1858
-                break;
1859
-
1860
-            case 'rangeOfInteger':
1861
-                // $value have to be: INT1:INT2 , eg 100:1000
1862
-                $this->job_tags[$attribute]['value'][] = self::_rangeOfIntegerBuild($value);
1863
-                break;
1864
-
1865
-            case 'resolution':
1866
-                if (preg_match("#dpi#", $value)) {
1867
-                    $unit = chr(0x3);
1868
-                }
1869
-                if (preg_match("#dpc#", $value)) {
1870
-                    $unit = chr(0x4);
1871
-                }
1872
-                $search = array(
1873
-                    "#(dpi|dpc)#",
1874
-                    '#(x|-)#'
1875
-                );
1876
-                $replace = array(
1877
-                    "",
1878
-                    ":"
1879
-                );
1880
-                $value = self::_rangeOfIntegerBuild(preg_replace($search, $replace, $value)) . $unit;
1881
-                $this->job_tags[$attribute]['value'][] = $value;
1882
-                break;
1883
-
1884
-            default:
1885
-                trigger_error(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , E_USER_NOTICE);
1886
-                self::_putDebug(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1887
-                self::_errorLog(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1888
-                return FALSE;
1889
-                break;
1890
-        }
1891
-        $this->job_tags[$attribute]['systag'] = $this->tags_types[$tag_type]['tag'];
1892
-    }
1893
-
1894
-    protected function _setOperationAttribute($attribute, $value)
1895
-    {
1896
-        //used by setAttribute
1897
-        $tag_type = $this->operation_tags[$attribute]['tag'];
1898
-        switch ($tag_type)
1899
-        {
1900
-            case 'integer':
1901
-                $this->operation_tags[$attribute]['value'][] = self::_integerBuild($value);
1902
-                break;
1903
-
1904
-            case 'keyword':
1905
-            case 'naturalLanguage':
1906
-                $this->operation_tags[$attribute]['value'][] = $value;
1907
-                break;
1908
-
1909
-            default:
1910
-                trigger_error(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , E_USER_NOTICE);
1911
-                self::_putDebug(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1912
-                self::_errorLog(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1913
-                return FALSE;
1914
-                break;
1915
-        }
1916
-        $this->operation_tags[$attribute]['systag'] = $this->tags_types[$tag_type]['tag'];
1917
-    }
1918
-
1919
-    protected function _setPrinterAttribute($attribute, $value)
1920
-    {
1921
-        //used by setAttribute
1922
-        $tag_type = $this->printer_tags[$attribute]['tag'];
1923
-        switch ($tag_type)
1924
-        {
1925
-            case 'integer':
1926
-                $this->printer_tags[$attribute]['value'][] = self::_integerBuild($value);
1927
-                break;
1928
-
1929
-            case 'keyword':
1930
-            case 'naturalLanguage':
1931
-                $this->printer_tags[$attribute]['value'][] = $value;
1932
-                break;
1933
-
1934
-            default:
1935
-                trigger_error(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , E_USER_NOTICE);
1936
-                self::_putDebug(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1937
-                self::_errorLog(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1938
-                return FALSE;
1939
-                break;
1940
-        }
1941
-        $this->printer_tags[$attribute]['systag'] = $this->tags_types[$tag_type]['tag'];
1942
-    }
1943
-
1944
-    //
1945
-    // DEBUGGING
1946
-    //
1947
-    protected function _putDebug($string, $level = 1)
1948
-    {
1949
-        if ($level === false) {
1950
-            return;
1951
-        }
1952
-
1953
-        if ($level < $this->debug_level) {
1954
-            return;
1955
-        }
1956
-
1957
-        $this->debug[$this->debug_count] = substr($string, 0, 1024);
1958
-        $this->debug_count++;
1959
-        //$this->debug .= substr($string,0,1024);
1960
-
1961
-    }
1962
-
1963
-    //
1964
-    // LOGGING
1965
-    //
1966
-    protected function _errorLog($string_to_log, $level)
1967
-    {
1968
-        if ($level > $this->log_level) {
1969
-            return;
1970
-        }
1971
-
1972
-        $string = sprintf('%s : %s:%s user %s : %s', basename($_SERVER['PHP_SELF']) , $this->host, $this->port, $this->requesting_user, $string_to_log);
1973
-
1974
-        if ($this->log_type == 0)
1975
-        {
1976
-            error_log($string);
1977
-            return;
1978
-        }
1979
-
1980
-        $string = sprintf("%s %s Host %s:%s user %s : %s\n", date('M d H:i:s') , basename($_SERVER['PHP_SELF']) , $this->host, $this->port, $this->requesting_user, $string_to_log);
1981
-        error_log($string, $this->log_type, $this->log_destination);
1982
-        return;
1983
-    }
993
+			"textWithoutLanguage" => array(
994
+				"tag" => chr(0x41) ,
995
+				"build" => "string"
996
+			) ,
997
+			"nameWithoutLanguage" => array(
998
+				"tag" => chr(0x42) ,
999
+				"buid" => "string"
1000
+			) ,
1001
+			"keyword" => array(
1002
+				"tag" => chr(0x44) ,
1003
+				"build" => "string"
1004
+			) ,
1005
+			"uri" => array(
1006
+				"tag" => chr(0x45) ,
1007
+				"build" => "string"
1008
+			) ,
1009
+			"uriScheme" => array(
1010
+				"tag" => chr(0x46) ,
1011
+				"build" => "string"
1012
+			) ,
1013
+			"charset" => array(
1014
+				"tag" => chr(0x47) ,
1015
+				"build" => "string"
1016
+			) ,
1017
+			"naturalLanguage" => array(
1018
+				"tag" => chr(0x48) ,
1019
+				"build" => "string"
1020
+			) ,
1021
+			"mimeMediaType" => array(
1022
+				"tag" => chr(0x49) ,
1023
+				"build" => "string"
1024
+			) ,
1025
+			"extendedAttributes" => array(
1026
+				"tag" => chr(0x7F) ,
1027
+				"build" => "extended"
1028
+			) ,
1029
+		);
1030
+		$this->operation_tags = array(
1031
+			"compression" => array(
1032
+				"tag" => "keyword"
1033
+			) ,
1034
+			"document-natural-language" => array(
1035
+				"tag" => "naturalLanguage"
1036
+			) ,
1037
+			"job-k-octets" => array(
1038
+				"tag" => "integer"
1039
+			) ,
1040
+			"job-impressions" => array(
1041
+				"tag" => "integer"
1042
+			) ,
1043
+			"job-media-sheets" => array(
1044
+				"tag" => "integer"
1045
+			) ,
1046
+		);
1047
+		$this->job_tags = array(
1048
+			"job-priority" => array(
1049
+				"tag" => "integer"
1050
+			) ,
1051
+			"job-hold-until" => array(
1052
+				"tag" => "keyword"
1053
+			) ,
1054
+			"job-sheets" => array(
1055
+				"tag" => "keyword"
1056
+			) , //banner page
1057
+			"multiple-document-handling" => array(
1058
+				"tag" => "keyword"
1059
+			) ,
1060
+			//"copies" => array("tag" => "integer"),
1061
+			"finishings" => array(
1062
+				"tag" => "enum"
1063
+			) ,
1064
+			//"page-ranges" => array("tag" => "rangeOfInteger"), // has its own function
1065
+			//"sides" => array("tag" => "keyword"), // has its own function
1066
+			"number-up" => array(
1067
+				"tag" => "integer"
1068
+			) ,
1069
+			"orientation-requested" => array(
1070
+				"tag" => "enum"
1071
+			) ,
1072
+			"media" => array(
1073
+				"tag" => "keyword"
1074
+			) ,
1075
+			"printer-resolution" => array(
1076
+				"tag" => "resolution"
1077
+			) ,
1078
+			"print-quality" => array(
1079
+				"tag" => "enum"
1080
+			) ,
1081
+			"job-message-from-operator" => array(
1082
+				"tag" => "textWithoutLanguage"
1083
+			) ,
1084
+		);
1085
+		$this->printer_tags = array(
1086
+			"requested-attributes" => array(
1087
+				"tag" => "keyword"
1088
+			)
1089
+		);
1090
+	}
1091
+
1092
+	//
1093
+	// SETUP
1094
+	//
1095
+	protected function _setOperationId()
1096
+	{
1097
+		$prepend = '';
1098
+		$this->operation_id+= 1;
1099
+		$this->meta->operation_id = self::_integerBuild($this->operation_id);
1100
+		self::_putDebug("operation id is: " . $this->operation_id, 2);
1101
+	}
1102
+
1103
+	protected function _setJobId()
1104
+	{
1105
+		$this->meta->jobid+= 1;
1106
+		$prepend = '';
1107
+		$prepend_length = 4 - strlen($this->meta->jobid);
1108
+		for ($i = 0; $i < $prepend_length; $i++) {
1109
+			$prepend.= '0';
1110
+		}
1111
+		return $prepend . $this->meta->jobid;
1112
+	}
1113
+
1114
+	protected function _setJobUri($job_uri)
1115
+	{
1116
+		$this->meta->job_uri = chr(0x45) // type uri
1117
+			. chr(0x00) . chr(0x07) // name-length
1118
+			. "job-uri"
1119
+			//. chr(0x00).chr(strlen($job_uri))
1120
+			. self::_giveMeStringLength($job_uri) . $job_uri;
1121
+		self::_putDebug("job-uri is: " . $job_uri, 2);
1122
+	}
1123
+
1124
+	//
1125
+	// RESPONSE PARSING
1126
+	//
1127
+	protected function _parseServerOutput()
1128
+	{
1129
+		$this->serveroutput->response = array();
1130
+		if (!self::_parseHttpHeaders()) {
1131
+			return FALSE;
1132
+		}
1133
+		$this->_parsing->offset = 0;
1134
+		self::_parseIppVersion();
1135
+		self::_parseStatusCode();
1136
+		self::_parseRequestID();
1137
+		$this->_parseResponse();
1138
+		//devel
1139
+		self::_putDebug(
1140
+			sprintf("***** IPP STATUS: %s ******", $this->serveroutput->status),
1141
+			4);
1142
+		self::_putDebug("****** END OF OPERATION ****");
1143
+		return true;
1144
+	}
1145
+
1146
+	protected function _parseHttpHeaders()
1147
+	{
1148
+		$response = "";
1149
+		switch ($this->serveroutput->headers[0])
1150
+		{
1151
+			case "http/1.1 200 ok: ":
1152
+				$this->serveroutput->httpstatus = "HTTP/1.1 200 OK";
1153
+				$response = "OK";
1154
+				break;
1155
+
1156
+			// primitive http/1.0 for Lexmark printers (from Rick Baril)
1157
+			case "http/1.0 200 ok: ":
1158
+				$this->serveroutput->httpstatus = "HTTP/1.0 200 OK";
1159
+				$response = "OK";
1160
+				break;
1161
+
1162
+			case "http/1.1 100 continue: ":
1163
+				$this->serveroutput->httpstatus = "HTTP/1.1 100 CONTINUE";
1164
+				$response = "OK";
1165
+				break;
1166
+
1167
+			case "":
1168
+				$this->serveroutput->httpstatus = "HTTP/1.1 000 No Response From Server";
1169
+				$this->serveroutput->status = "HTTP-ERROR-000_NO_RESPONSE_FROM_SERVER";
1170
+				trigger_error("No Response From Server", E_USER_WARNING);
1171
+				self::_errorLog("No Response From Server", 1);
1172
+				$this->disconnected = 1;
1173
+				return FALSE;
1174
+				break;
1175
+
1176
+			default:
1177
+				$server_response = preg_replace("/: $/", '', $this->serveroutput->headers[0]);
1178
+				#$strings = split(' ', $server_response, 3);
1179
+				$strings = preg_split('# #', $server_response, 3);
1180
+				$errno = $strings[1];
1181
+				$string = strtoupper(str_replace(' ', '_', $strings[2]));
1182
+				trigger_error(
1183
+					sprintf(_("server responds %s") , $server_response),
1184
+					E_USER_WARNING);
1185
+				self::_errorLog("server responds " . $server_response, 1);
1186
+				$this->serveroutput->httpstatus =
1187
+					strtoupper($strings[0])
1188
+						. " "
1189
+						. $errno
1190
+						. " "
1191
+						. ucfirst($strings[2]);
1192
+
1193
+				$this->serveroutput->status =
1194
+					"HTTP-ERROR-"
1195
+						. $errno
1196
+						. "-"
1197
+						. $string;
1198
+				$this->disconnected = 1;
1199
+				return FALSE;
1200
+				break;
1201
+		}
1202
+		unset($this->serveroutput->headers);
1203
+		return TRUE;
1204
+	}
1205
+
1206
+	protected function _parseIppVersion()
1207
+	{
1208
+		$ippversion =
1209
+			(ord($this->serveroutput->body[$this->_parsing->offset]) * 256)
1210
+				+ ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1211
+		switch ($ippversion)
1212
+		{
1213
+			case 0x0101:
1214
+				$this->serveroutput->ipp_version = "1.1";
1215
+				break;
1216
+
1217
+			default:
1218
+				$this->serveroutput->ipp_version =
1219
+					sprintf("%u.%u (Unknown)",
1220
+						ord($this->serveroutput->body[$this->_parsing->offset]) * 256,
1221
+						ord($this->serveroutput->body[$this->_parsing->offset + 1]));
1222
+				break;
1223
+		}
1224
+		self::_putDebug("I P P    R E S P O N S E :\n\n");
1225
+		self::_putDebug(
1226
+			sprintf("IPP version %s%s: %s",
1227
+				ord($this->serveroutput->body[$this->_parsing->offset]),
1228
+				ord($this->serveroutput->body[$this->_parsing->offset + 1]),
1229
+				$this->serveroutput->ipp_version));
1230
+		$this->_parsing->offset+= 2;
1231
+		return;
1232
+	}
1233
+
1234
+	protected function _parseStatusCode()
1235
+	{
1236
+		$status_code =
1237
+			(ord($this->serveroutput->body[$this->_parsing->offset]) * 256)
1238
+			+ ord($this->serveroutput->body[$this->_parsing->offset + 1]);
1239
+		$this->serveroutput->status = "NOT PARSED";
1240
+		$this->_parsing->offset+= 2;
1241
+		if (strlen($this->serveroutput->body) < $this->_parsing->offset)
1242
+		{
1243
+			return false;
1244
+		}
1245
+		if ($status_code < 0x00FF)
1246
+		{
1247
+			$this->serveroutput->status = "successfull";
1248
+		}
1249
+		elseif ($status_code < 0x01FF)
1250
+		{
1251
+			$this->serveroutput->status = "informational";
1252
+		}
1253
+		elseif ($status_code < 0x02FF)
1254
+		{
1255
+			$this->serveroutput->status = "redirection";
1256
+		}
1257
+		elseif ($status_code < 0x04FF)
1258
+		{
1259
+			$this->serveroutput->status = "client-error";
1260
+		}
1261
+		elseif ($status_code < 0x05FF)
1262
+		{
1263
+			$this->serveroutput->status = "server-error";
1264
+		}
1265
+		switch ($status_code)
1266
+		{
1267
+			case 0x0000:
1268
+				$this->serveroutput->status = "successfull-ok";
1269
+				break;
1270
+
1271
+			case 0x0001:
1272
+				$this->serveroutput->status = "successful-ok-ignored-or-substituted-attributes";
1273
+				break;
1274
+
1275
+			case 0x002:
1276
+				$this->serveroutput->status = "successful-ok-conflicting-attributes";
1277
+				break;
1278
+
1279
+			case 0x0400:
1280
+				$this->serveroutput->status = "client-error-bad-request";
1281
+				break;
1282
+
1283
+			case 0x0401:
1284
+				$this->serveroutput->status = "client-error-forbidden";
1285
+				break;
1286
+
1287
+			case 0x0402:
1288
+				$this->serveroutput->status = "client-error-not-authenticated";
1289
+				break;
1290
+
1291
+			case 0x0403:
1292
+				$this->serveroutput->status = "client-error-not-authorized";
1293
+				break;
1294
+
1295
+			case 0x0404:
1296
+				$this->serveroutput->status = "client-error-not-possible";
1297
+				break;
1298
+
1299
+			case 0x0405:
1300
+				$this->serveroutput->status = "client-error-timeout";
1301
+				break;
1302
+
1303
+			case 0x0406:
1304
+				$this->serveroutput->status = "client-error-not-found";
1305
+				break;
1306
+
1307
+			case 0x0407:
1308
+				$this->serveroutput->status = "client-error-gone";
1309
+				break;
1310
+
1311
+			case 0x0408:
1312
+				$this->serveroutput->status = "client-error-request-entity-too-large";
1313
+				break;
1314
+
1315
+			case 0x0409:
1316
+				$this->serveroutput->status = "client-error-request-value-too-long";
1317
+				break;
1318
+
1319
+			case 0x040A:
1320
+				$this->serveroutput->status = "client-error-document-format-not-supported";
1321
+				break;
1322
+
1323
+			case 0x040B:
1324
+				$this->serveroutput->status = "client-error-attributes-or-values-not-supported";
1325
+				break;
1326
+
1327
+			case 0x040C:
1328
+				$this->serveroutput->status = "client-error-uri-scheme-not-supported";
1329
+				break;
1330
+
1331
+			case 0x040D:
1332
+				$this->serveroutput->status = "client-error-charset-not-supported";
1333
+				break;
1334
+
1335
+			case 0x040E:
1336
+				$this->serveroutput->status = "client-error-conflicting-attributes";
1337
+				break;
1338
+
1339
+			case 0x040F:
1340
+				$this->serveroutput->status = "client-error-compression-not-supported";
1341
+				break;
1342
+
1343
+			case 0x0410:
1344
+				$this->serveroutput->status = "client-error-compression-error";
1345
+				break;
1346
+
1347
+			case 0x0411:
1348
+				$this->serveroutput->status = "client-error-document-format-error";
1349
+				break;
1350
+
1351
+			case 0x0412:
1352
+				$this->serveroutput->status = "client-error-document-access-error";
1353
+				break;
1354
+
1355
+			case 0x0413: // RFC3380
1356
+				$this->serveroutput->status = "client-error-attributes-not-settable";
1357
+				break;
1358
+
1359
+			case 0x0500:
1360
+				$this->serveroutput->status = "server-error-internal-error";
1361
+				break;
1362
+
1363
+			case 0x0501:
1364
+				$this->serveroutput->status = "server-error-operation-not-supported";
1365
+				break;
1366
+
1367
+			case 0x0502:
1368
+				$this->serveroutput->status = "server-error-service-unavailable";
1369
+				break;
1370
+
1371
+			case 0x0503:
1372
+				$this->serveroutput->status = "server-error-version-not-supported";
1373
+				break;
1374
+
1375
+			case 0x0504:
1376
+				$this->serveroutput->status = "server-error-device-error";
1377
+				break;
1378
+
1379
+			case 0x0505:
1380
+				$this->serveroutput->status = "server-error-temporary-error";
1381
+				break;
1382
+
1383
+			case 0x0506:
1384
+				$this->serveroutput->status = "server-error-not-accepting-jobs";
1385
+				break;
1386
+
1387
+			case 0x0507:
1388
+				$this->serveroutput->status = "server-error-busy";
1389
+				break;
1390
+
1391
+			case 0x0508:
1392
+				$this->serveroutput->status = "server-error-job-canceled";
1393
+				break;
1394
+
1395
+			case 0x0509:
1396
+				$this->serveroutput->status = "server-error-multiple-document-jobs-not-supported";
1397
+				break;
1398
+
1399
+			default:
1400
+				break;
1401
+		}
1402
+		self::_putDebug(
1403
+			sprintf(
1404
+				"status-code: %s%s: %s ",
1405
+				$this->serveroutput->body[$this->_parsing->offset],
1406
+				$this->serveroutput->body[$this->_parsing->offset + 1],
1407
+				$this->serveroutput->status),
1408
+			4);
1409
+		return;
1410
+	}
1411
+
1412
+	protected function _parseRequestID()
1413
+	{
1414
+		$this->serveroutput->request_id =
1415
+			self::_interpretInteger(
1416
+				substr($this->serveroutput->body, $this->_parsing->offset, 4)
1417
+			);
1418
+		self::_putDebug("request-id " . $this->serveroutput->request_id, 2);
1419
+		$this->_parsing->offset+= 4;
1420
+		return;
1421
+	}
1422
+
1423
+	protected function _interpretInteger($value)
1424
+	{
1425
+		// they are _signed_ integers
1426
+		$value_parsed = 0;
1427
+		for ($i = strlen($value); $i > 0; $i --)
1428
+		{
1429
+			$value_parsed +=
1430
+				(
1431
+					(1 << (($i - 1) * 8))
1432
+						*
1433
+						ord($value[strlen($value) - $i])
1434
+				);
1435
+		}
1436
+		if ($value_parsed >= 2147483648)
1437
+		{
1438
+			$value_parsed -= 4294967296;
1439
+		}
1440
+		return $value_parsed;
1441
+	}
1442
+
1443
+	protected function _parseResponse()
1444
+	{
1445
+	}
1446
+
1447
+	//
1448
+	// REQUEST BUILDING
1449
+	//
1450
+	protected function _stringJob()
1451
+	{
1452
+		if (!isset($this->setup->charset)) {
1453
+			self::setCharset();
1454
+		}
1455
+		if (!isset($this->setup->datatype)) {
1456
+			self::setBinary();
1457
+		}
1458
+		if (!isset($this->setup->uri))
1459
+		{
1460
+			$this->getPrinters();
1461
+			unset($this->jobs[count($this->jobs) - 1]);
1462
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
1463
+			unset($this->status[count($this->status) - 1]);
1464
+			if (array_key_exists(0, $this->available_printers))
1465
+			{
1466
+				self::setPrinterURI($this->available_printers[0]);
1467
+			}
1468
+			else
1469
+			{
1470
+				trigger_error(
1471
+					_("_stringJob: Printer URI is not set: die"),
1472
+					E_USER_WARNING);
1473
+				self::_putDebug(_("_stringJob: Printer URI is not set: die") , 4);
1474
+				self::_errorLog(" Printer URI is not set, die", 2);
1475
+				return FALSE;
1476
+			}
1477
+		}
1478
+		if (!isset($this->setup->copies)) {
1479
+			self::setCopies(1);
1480
+		}
1481
+		if (!isset($this->setup->language)) {
1482
+			self::setLanguage('en_us');
1483
+		}
1484
+		if (!isset($this->setup->mime_media_type)) {
1485
+			self::setMimeMediaType();
1486
+		}
1487
+		if (!isset($this->setup->jobname)) {
1488
+			self::setJobName();
1489
+		}
1490
+		unset($this->setup->jobname);
1491
+		if (!isset($this->meta->username)) {
1492
+			self::setUserName();
1493
+		}
1494
+		if (!isset($this->meta->fidelity)) {
1495
+			$this->meta->fidelity = '';
1496
+		}
1497
+		if (!isset($this->meta->document_name)) {
1498
+			$this->meta->document_name = '';
1499
+		}
1500
+		if (!isset($this->meta->sides)) {
1501
+			$this->meta->sides = '';
1502
+		}
1503
+		if (!isset($this->meta->page_ranges)) {
1504
+			$this->meta->page_ranges = '';
1505
+		}
1506
+		$jobattributes = '';
1507
+		$operationattributes = '';
1508
+		$printerattributes = '';
1509
+		$this->_buildValues($operationattributes, $jobattributes, $printerattributes);
1510
+		self::_setOperationId();
1511
+		if (!isset($this->error_generation->request_body_malformed))
1512
+		{
1513
+			$this->error_generation->request_body_malformed = "";
1514
+		}
1515
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1516
+			. chr(0x00) . chr(0x02) // Print-Job | operation-id
1517
+			. $this->meta->operation_id //           request-id
1518
+			. chr(0x01) // start operation-attributes | operation-attributes-tag
1519
+			. $this->meta->charset
1520
+			. $this->meta->language
1521
+			. $this->meta->printer_uri
1522
+			. $this->meta->username
1523
+			. $this->meta->jobname
1524
+			. $this->meta->fidelity
1525
+			. $this->meta->document_name
1526
+			. $this->meta->mime_media_type
1527
+			. $operationattributes;
1528
+		if ($this->meta->copies || $this->meta->sides || $this->meta->page_ranges || !empty($jobattributes))
1529
+		{
1530
+			$this->stringjob .=
1531
+				chr(0x02) // start job-attributes | job-attributes-tag
1532
+					. $this->meta->copies
1533
+					. $this->meta->sides
1534
+					. $this->meta->page_ranges
1535
+					. $jobattributes;
1536
+		}
1537
+		$this->stringjob.= chr(0x03); // end-of-attributes | end-of-attributes-tag
1538
+		self::_putDebug(
1539
+			sprintf(_("String sent to the server is: %s"),
1540
+				$this->stringjob)
1541
+			);
1542
+		return TRUE;
1543
+	}
1544
+
1545
+	protected function _buildValues(&$operationattributes, &$jobattributes, &$printerattributes)
1546
+	{
1547
+		$operationattributes = '';
1548
+		foreach($this->operation_tags as $key => $values)
1549
+		{
1550
+			$item = 0;
1551
+			if (array_key_exists('value', $values))
1552
+			{
1553
+				foreach($values['value'] as $item_value)
1554
+				{
1555
+					if ($item == 0)
1556
+					{
1557
+						$operationattributes .=
1558
+							$values['systag']
1559
+								. self::_giveMeStringLength($key)
1560
+								. $key
1561
+								. self::_giveMeStringLength($item_value)
1562
+								. $item_value;
1563
+					}
1564
+					else
1565
+					{
1566
+						$operationattributes .=
1567
+							$values['systag']
1568
+								. self::_giveMeStringLength('')
1569
+								. self::_giveMeStringLength($item_value)
1570
+								. $item_value;
1571
+					}
1572
+					$item++;
1573
+				}
1574
+			}
1575
+		}
1576
+		$jobattributes = '';
1577
+		foreach($this->job_tags as $key => $values)
1578
+		{
1579
+			$item = 0;
1580
+			if (array_key_exists('value', $values))
1581
+			{
1582
+				foreach($values['value'] as $item_value)
1583
+				{
1584
+					if ($item == 0)
1585
+					{
1586
+						$jobattributes .=
1587
+							$values['systag']
1588
+								. self::_giveMeStringLength($key)
1589
+								. $key
1590
+								. self::_giveMeStringLength($item_value)
1591
+								. $item_value;
1592
+					}
1593
+					else
1594
+					{
1595
+						$jobattributes .=
1596
+							$values['systag']
1597
+								. self::_giveMeStringLength('')
1598
+								. self::_giveMeStringLength($item_value)
1599
+								. $item_value;
1600
+					}
1601
+					$item++;
1602
+				}
1603
+			}
1604
+		}
1605
+		$printerattributes = '';
1606
+		foreach($this->printer_tags as $key => $values)
1607
+		{
1608
+			$item = 0;
1609
+			if (array_key_exists('value', $values))
1610
+			{
1611
+				foreach($values['value'] as $item_value)
1612
+				{
1613
+					if ($item == 0)
1614
+					{
1615
+						$printerattributes .=
1616
+							$values['systag']
1617
+								. self::_giveMeStringLength($key)
1618
+								. $key
1619
+								. self::_giveMeStringLength($item_value)
1620
+								. $item_value;
1621
+					}
1622
+					else
1623
+					{
1624
+						$printerattributes .=
1625
+							$values['systag']
1626
+								. self::_giveMeStringLength('')
1627
+								. self::_giveMeStringLength($item_value)
1628
+								. $item_value;
1629
+					}
1630
+					$item++;
1631
+				}
1632
+			}
1633
+		}
1634
+		reset($this->job_tags);
1635
+		reset($this->operation_tags);
1636
+		reset($this->printer_tags);
1637
+		return true;
1638
+	}
1639
+
1640
+	protected function _giveMeStringLength($string)
1641
+	{
1642
+		$length = strlen($string);
1643
+		if ($length > ((0xFF << 8) + 0xFF)  )
1644
+		{
1645
+			$errmsg = sprintf (
1646
+				_('max string length for an ipp meta-information = %d, while here %d'),
1647
+				((0xFF << 8) + 0xFF), $length);
1648
+
1649
+			if ($this->with_exceptions)
1650
+			{
1651
+				throw new ippException($errmsg);
1652
+			}
1653
+			else
1654
+			{
1655
+				trigger_error ($errmsg, E_USER_ERROR);
1656
+			}
1657
+		}
1658
+		$int1 = $length & 0xFF;
1659
+		$length -= $int1;
1660
+		$length = $length >> 8;
1661
+		$int2 = $length & 0xFF;
1662
+		return chr($int2) . chr($int1);
1663
+	}
1664
+
1665
+	protected function _enumBuild($tag, $value)
1666
+	{
1667
+		switch ($tag)
1668
+		{
1669
+			case "orientation-requested":
1670
+				switch ($value)
1671
+				{
1672
+					case 'portrait':
1673
+						$value = chr(3);
1674
+						break;
1675
+
1676
+					case 'landscape':
1677
+						$value = chr(4);
1678
+						break;
1679
+
1680
+					case 'reverse-landscape':
1681
+						$value = chr(5);
1682
+						break;
1683
+
1684
+					case 'reverse-portrait':
1685
+						$value = chr(6);
1686
+						break;
1687
+				}
1688
+				break;
1689
+
1690
+			case "print-quality":
1691
+				switch ($value)
1692
+				{
1693
+					case 'draft':
1694
+						$value = chr(3);
1695
+						break;
1696
+
1697
+					case 'normal':
1698
+						$value = chr(4);
1699
+						break;
1700
+
1701
+					case 'high':
1702
+						$value = chr(5);
1703
+						break;
1704
+				}
1705
+				break;
1706
+
1707
+			case "finishing":
1708
+				switch ($value)
1709
+				{
1710
+					case 'none':
1711
+						$value = chr(3);
1712
+						break;
1713
+
1714
+					case 'staple':
1715
+						$value = chr(4);
1716
+						break;
1717
+
1718
+					case 'punch':
1719
+						$value = chr(5);
1720
+						break;
1721
+
1722
+					case 'cover':
1723
+						$value = chr(6);
1724
+						break;
1725
+
1726
+					case 'bind':
1727
+						$value = chr(7);
1728
+						break;
1729
+
1730
+					case 'saddle-stitch':
1731
+						$value = chr(8);
1732
+						break;
1733
+
1734
+					case 'edge-stitch':
1735
+						$value = chr(9);
1736
+						break;
1737
+
1738
+					case 'staple-top-left':
1739
+						$value = chr(20);
1740
+						break;
1741
+
1742
+					case 'staple-bottom-left':
1743
+						$value = chr(21);
1744
+						break;
1745
+
1746
+					case 'staple-top-right':
1747
+						$value = chr(22);
1748
+						break;
1749
+
1750
+					case 'staple-bottom-right':
1751
+						$value = chr(23);
1752
+						break;
1753
+
1754
+					case 'edge-stitch-left':
1755
+						$value = chr(24);
1756
+						break;
1757
+
1758
+					case 'edge-stitch-top':
1759
+						$value = chr(25);
1760
+						break;
1761
+
1762
+					case 'edge-stitch-right':
1763
+						$value = chr(26);
1764
+						break;
1765
+
1766
+					case 'edge-stitch-bottom':
1767
+						$value = chr(27);
1768
+						break;
1769
+
1770
+					case 'staple-dual-left':
1771
+						$value = chr(28);
1772
+						break;
1773
+
1774
+					case 'staple-dual-top':
1775
+						$value = chr(29);
1776
+						break;
1777
+
1778
+					case 'staple-dual-right':
1779
+						$value = chr(30);
1780
+						break;
1781
+
1782
+					case 'staple-dual-bottom':
1783
+						$value = chr(31);
1784
+						break;
1785
+				}
1786
+				break;
1787
+		}
1788
+		$prepend = '';
1789
+		while ((strlen($value) + strlen($prepend)) < 4)
1790
+		{
1791
+			$prepend .= chr(0);
1792
+		}
1793
+		return $prepend . $value;
1794
+	}
1795
+
1796
+	protected function _integerBuild($value)
1797
+	{
1798
+		if ($value >= 2147483647 || $value < - 2147483648)
1799
+		{
1800
+			trigger_error(
1801
+				_("Values must be between -2147483648 and 2147483647: assuming '0'") , E_USER_WARNING);
1802
+			return chr(0x00) . chr(0x00) . chr(0x00) . chr(0x00);
1803
+		}
1804
+		$initial_value = $value;
1805
+		$int1 = $value & 0xFF;
1806
+		$value -= $int1;
1807
+		$value = $value >> 8;
1808
+		$int2 = $value & 0xFF;
1809
+		$value-= $int2;
1810
+		$value = $value >> 8;
1811
+		$int3 = $value & 0xFF;
1812
+		$value-= $int3;
1813
+		$value = $value >> 8;
1814
+		$int4 = $value & 0xFF; //64bits
1815
+		if ($initial_value < 0) {
1816
+			$int4 = chr($int4) | chr(0x80);
1817
+		}
1818
+		else {
1819
+			$int4 = chr($int4);
1820
+		}
1821
+		$value = $int4 . chr($int3) . chr($int2) . chr($int1);
1822
+		return $value;
1823
+	}
1824
+
1825
+	protected function _rangeOfIntegerBuild($integers)
1826
+	{
1827
+		#$integers = split(":", $integers);
1828
+		$integers = preg_split("#:#", $integers);
1829
+		for ($i = 0; $i < 2; $i++) {
1830
+			$outvalue[$i] = self::_integerBuild($integers[$i]);
1831
+		}
1832
+		return $outvalue[0] . $outvalue[1];
1833
+	}
1834
+
1835
+	protected function _setJobAttribute($attribute, $value)
1836
+	{
1837
+		//used by setAttribute
1838
+		$tag_type = $this->job_tags[$attribute]['tag'];
1839
+		switch ($tag_type)
1840
+		{
1841
+			case 'integer':
1842
+				$this->job_tags[$attribute]['value'][] = self::_integerBuild($value);
1843
+				break;
1844
+
1845
+			case 'boolean':
1846
+			case 'nameWithoutLanguage':
1847
+			case 'nameWithLanguage':
1848
+			case 'textWithoutLanguage':
1849
+			case 'textWithLanguage':
1850
+			case 'keyword':
1851
+			case 'naturalLanguage':
1852
+				$this->job_tags[$attribute]['value'][] = $value;
1853
+				break;
1854
+
1855
+			case 'enum':
1856
+				$value = $this->_enumBuild($attribute, $value); // may be overwritten by children
1857
+				$this->job_tags[$attribute]['value'][] = $value;
1858
+				break;
1859
+
1860
+			case 'rangeOfInteger':
1861
+				// $value have to be: INT1:INT2 , eg 100:1000
1862
+				$this->job_tags[$attribute]['value'][] = self::_rangeOfIntegerBuild($value);
1863
+				break;
1864
+
1865
+			case 'resolution':
1866
+				if (preg_match("#dpi#", $value)) {
1867
+					$unit = chr(0x3);
1868
+				}
1869
+				if (preg_match("#dpc#", $value)) {
1870
+					$unit = chr(0x4);
1871
+				}
1872
+				$search = array(
1873
+					"#(dpi|dpc)#",
1874
+					'#(x|-)#'
1875
+				);
1876
+				$replace = array(
1877
+					"",
1878
+					":"
1879
+				);
1880
+				$value = self::_rangeOfIntegerBuild(preg_replace($search, $replace, $value)) . $unit;
1881
+				$this->job_tags[$attribute]['value'][] = $value;
1882
+				break;
1883
+
1884
+			default:
1885
+				trigger_error(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , E_USER_NOTICE);
1886
+				self::_putDebug(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1887
+				self::_errorLog(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1888
+				return FALSE;
1889
+				break;
1890
+		}
1891
+		$this->job_tags[$attribute]['systag'] = $this->tags_types[$tag_type]['tag'];
1892
+	}
1893
+
1894
+	protected function _setOperationAttribute($attribute, $value)
1895
+	{
1896
+		//used by setAttribute
1897
+		$tag_type = $this->operation_tags[$attribute]['tag'];
1898
+		switch ($tag_type)
1899
+		{
1900
+			case 'integer':
1901
+				$this->operation_tags[$attribute]['value'][] = self::_integerBuild($value);
1902
+				break;
1903
+
1904
+			case 'keyword':
1905
+			case 'naturalLanguage':
1906
+				$this->operation_tags[$attribute]['value'][] = $value;
1907
+				break;
1908
+
1909
+			default:
1910
+				trigger_error(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , E_USER_NOTICE);
1911
+				self::_putDebug(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1912
+				self::_errorLog(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1913
+				return FALSE;
1914
+				break;
1915
+		}
1916
+		$this->operation_tags[$attribute]['systag'] = $this->tags_types[$tag_type]['tag'];
1917
+	}
1918
+
1919
+	protected function _setPrinterAttribute($attribute, $value)
1920
+	{
1921
+		//used by setAttribute
1922
+		$tag_type = $this->printer_tags[$attribute]['tag'];
1923
+		switch ($tag_type)
1924
+		{
1925
+			case 'integer':
1926
+				$this->printer_tags[$attribute]['value'][] = self::_integerBuild($value);
1927
+				break;
1928
+
1929
+			case 'keyword':
1930
+			case 'naturalLanguage':
1931
+				$this->printer_tags[$attribute]['value'][] = $value;
1932
+				break;
1933
+
1934
+			default:
1935
+				trigger_error(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , E_USER_NOTICE);
1936
+				self::_putDebug(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1937
+				self::_errorLog(sprintf(_('SetAttribute: Tag "%s": cannot set attribute') , $attribute) , 2);
1938
+				return FALSE;
1939
+				break;
1940
+		}
1941
+		$this->printer_tags[$attribute]['systag'] = $this->tags_types[$tag_type]['tag'];
1942
+	}
1943
+
1944
+	//
1945
+	// DEBUGGING
1946
+	//
1947
+	protected function _putDebug($string, $level = 1)
1948
+	{
1949
+		if ($level === false) {
1950
+			return;
1951
+		}
1952
+
1953
+		if ($level < $this->debug_level) {
1954
+			return;
1955
+		}
1956
+
1957
+		$this->debug[$this->debug_count] = substr($string, 0, 1024);
1958
+		$this->debug_count++;
1959
+		//$this->debug .= substr($string,0,1024);
1960
+
1961
+	}
1962
+
1963
+	//
1964
+	// LOGGING
1965
+	//
1966
+	protected function _errorLog($string_to_log, $level)
1967
+	{
1968
+		if ($level > $this->log_level) {
1969
+			return;
1970
+		}
1971
+
1972
+		$string = sprintf('%s : %s:%s user %s : %s', basename($_SERVER['PHP_SELF']) , $this->host, $this->port, $this->requesting_user, $string_to_log);
1973
+
1974
+		if ($this->log_type == 0)
1975
+		{
1976
+			error_log($string);
1977
+			return;
1978
+		}
1979
+
1980
+		$string = sprintf("%s %s Host %s:%s user %s : %s\n", date('M d H:i:s') , basename($_SERVER['PHP_SELF']) , $this->host, $this->port, $this->requesting_user, $string_to_log);
1981
+		error_log($string, $this->log_type, $this->log_destination);
1982
+		return;
1983
+	}
1984 1984
 }
Please login to merge, or discard this patch.
htdocs/includes/printipp/ExtendedPrintIPP.php 1 patch
Indentation   +1575 added lines, -1575 removed lines patch added patch discarded remove patch
@@ -45,1084 +45,1084 @@  discard block
 block discarded – undo
45 45
 
46 46
 class ExtendedPrintIPP extends PrintIPP
47 47
 {
48
-    public function __construct()
49
-    {
50
-        parent::__construct();
51
-    }
52
-
53
-
54
-    // OPERATIONS
55
-    public function printURI ($uri)
56
-    {
57
-
58
-        self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
59
-
60
-        if (!empty($uri))
61
-        {
62
-            $this->document_uri = $uri;
63
-            $this->setup->uri = 1;
64
-        }
65
-
66
-        if(!$this->_stringUri())
67
-        {
68
-            return FALSE;
69
-        }
70
-
71
-        $this->output = $this->stringjob;
72
-
73
-        $post_values = array( "Content-Type" => "application/ipp",
74
-                              "Data" => $this->output);
75
-
76
-        if (self::_sendHttp ($post_values,$this->paths['printers']))
77
-        {
78
-            if(self::_parseServerOutput())
79
-            {
80
-                $this->_parseJobAttributes();
81
-                $this->_getJobId();
82
-                //$this->_getPrinterUri();
83
-                $this->_getJobUri();
84
-                }
85
-            }
86
-
87
-        $this->attributes = &$this->job_attributes;
88
-
89
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
90
-        {
91
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
92
-            if ($this->serveroutput->status == "successfull-ok")
93
-            {
94
-                self::_errorLog(sprintf("printing uri %s, job %s: ",$uri,$this->last_job)
95
-                            .$this->serveroutput->status,3);
96
-            }
97
-            else
98
-            {
99
-                $this->jobs = array_merge($this->jobs,array(""));
100
-                $this->jobs_uri = array_merge($this->jobs_uri,array(""));
101
-                self::_errorLog(sprintf("printing uri %s: ",$uri,$this->last_job)
102
-                            .$this->serveroutput->status,1);
103
-            }
104
-            return $this->serveroutput->status; 
105
-        }
106
-
107
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
108
-        self::_errorLog("printing uri $uri : OPERATION FAILED",1);
109
-
110
-        return false;
111
-    }
112
-
113
-
114
-    public function purgeJobs()
115
-    {
116
-        $this->jobs = array_merge($this->jobs,array(""));
117
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
118
-
119
-        self::_setOperationId();
120
-        $this->parsed = array();
121
-        unset($this->printer_attributes);
122
-
123
-        if (!isset($this->setup->uri))
124
-        {
125
-            $this->getPrinters();
126
-            unset($this->jobs[count($this->jobs) - 1]);
127
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
128
-            unset($this->status[count($this->status) - 1]);
129
-
130
-            if (array_key_exists(0,$this->available_printers))
131
-            {
132
-               self::setPrinterURI($this->available_printers[0]);
133
-            }
134
-            else
135
-            {
136
-                trigger_error(_("purgeJobs: Printer URI is not set: die"),E_USER_WARNING);
137
-                self::_putDebug( _("purgeJobs: Printer URI is not set: die\n"));
138
-                self::_errorLog("purgeJobs: Printer URI is not set, die",2);
139
-                return FALSE;
140
-                }
141
-            }
142
-
143
-        if (!isset($this->setup->charset))
144
-        {
145
-            self::setCharset();
146
-        }
147
-
148
-        if (!isset($this->setup->language))
149
-        {
150
-            self::setLanguage('en_us');
151
-        }
152
-
153
-        if (!isset($this->meta->username))
154
-        {
155
-            self::setUserName();
156
-        }
157
-
158
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
159
-                         . chr(0x00) . chr (0x12) // purge-Jobs | operation-id
160
-                         . $this->meta->operation_id //           request-id
161
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
162
-                         . $this->meta->charset
163
-                         . $this->meta->language
164
-                         . $this->meta->printer_uri
165
-                         . $this->meta->username
166
-                         . chr(0x22)
167
-                         . self::_giveMeStringLength("purge-jobs")
168
-                         . "purge-jobs"
169
-                         . self::_giveMeStringLength(chr(0x01))
170
-                         . chr(0x01)
171
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
172
-
173
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
174
-
175
-        self::_putDebug(sprintf(_("purging jobs of %s\n"),$this->printer_uri)); 
176
-
177
-        $this->output = $this->stringjob;
178
-
179
-        $post_values = array( "Content-Type"=>"application/ipp",
180
-                              "Data"=>$this->output);
181
-
182
-        if (self::_sendHttp ($post_values,$this->paths['admin']))
183
-        {
184
-            self::_parseServerOutput();
185
-            self::_parseAttributes();
186
-            }
187
-
188
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
189
-        {
190
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
191
-
192
-            if ($this->serveroutput->status == "successfull-ok")
193
-            {
194
-                self::_errorLog(sprintf(_("purging jobs of %s: "),$this->printer_uri)
195
-                            .$this->serveroutput->status,3);
196
-            }
197
-            else
198
-            {
199
-                 self::_errorLog(sprintf(_("purging jobs of %s: "),$this->printer_uri)
200
-                                             .$this->serveroutput->status,1);
201
-            }
202
-
203
-            return $this->serveroutput->status; 
204
-        }
205
-
206
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
207
-        self::_errorLog(date("Y-m-d H:i:s : ")
208
-                        .basename($_SERVER['PHP_SELF'])
209
-                        .sprintf(_("purging jobs of %s : OPERATION FAILED"),
210
-                                     $this->printer_uri),3);
211
-
212
-        return false;
213
-    }
214
-
215
-    public function createJob()
216
-    {
217
-        self::_setOperationId();
218
-        $this->parsed = array();
219
-        unset($this->printer_attributes);
220
-
221
-        if (!isset($this->setup->uri))
222
-        {
223
-            $this->getPrinters();
224
-            unset($this->jobs[count($this->jobs) - 1]);
225
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
226
-            unset($this->status[count($this->status) - 1]);
227
-
228
-            if (array_key_exists(0,$this->available_printers))
229
-            {
230
-               self::setPrinterURI($this->available_printers[0]);
231
-            }
232
-            else
233
-            {
234
-                trigger_error(_("createJob: Printer URI is not set: die"),E_USER_WARNING);
235
-                self::_putDebug( _("createJob: Printer URI is not set: die\n"));
236
-                self::_errorLog("createJob: Printer URI is not set, die",2);
237
-                return FALSE;
238
-                }
239
-            }
240
-
241
-        if (!isset($this->setup->charset))
242
-        {
243
-            self::setCharset();
244
-        }
245
-
246
-        if (!isset($this->setup->language))
247
-        {
248
-            self::setLanguage('en_us');
249
-        }
250
-
251
-        if (!isset($this->meta->username))
252
-        {
253
-            self::setUserName();
254
-        }
255
-
256
-        if (!isset($this->setup->copies))
257
-        {
258
-            self::setCopies(1);
259
-        }
260
-
261
-        if (!isset($this->meta->fidelity))
262
-        {
263
-            $this->meta->fidelity = '';
264
-        }
48
+	public function __construct()
49
+	{
50
+		parent::__construct();
51
+	}
52
+
53
+
54
+	// OPERATIONS
55
+	public function printURI ($uri)
56
+	{
57
+
58
+		self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
59
+
60
+		if (!empty($uri))
61
+		{
62
+			$this->document_uri = $uri;
63
+			$this->setup->uri = 1;
64
+		}
65
+
66
+		if(!$this->_stringUri())
67
+		{
68
+			return FALSE;
69
+		}
70
+
71
+		$this->output = $this->stringjob;
72
+
73
+		$post_values = array( "Content-Type" => "application/ipp",
74
+							  "Data" => $this->output);
75
+
76
+		if (self::_sendHttp ($post_values,$this->paths['printers']))
77
+		{
78
+			if(self::_parseServerOutput())
79
+			{
80
+				$this->_parseJobAttributes();
81
+				$this->_getJobId();
82
+				//$this->_getPrinterUri();
83
+				$this->_getJobUri();
84
+				}
85
+			}
86
+
87
+		$this->attributes = &$this->job_attributes;
88
+
89
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
90
+		{
91
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
92
+			if ($this->serveroutput->status == "successfull-ok")
93
+			{
94
+				self::_errorLog(sprintf("printing uri %s, job %s: ",$uri,$this->last_job)
95
+							.$this->serveroutput->status,3);
96
+			}
97
+			else
98
+			{
99
+				$this->jobs = array_merge($this->jobs,array(""));
100
+				$this->jobs_uri = array_merge($this->jobs_uri,array(""));
101
+				self::_errorLog(sprintf("printing uri %s: ",$uri,$this->last_job)
102
+							.$this->serveroutput->status,1);
103
+			}
104
+			return $this->serveroutput->status; 
105
+		}
106
+
107
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
108
+		self::_errorLog("printing uri $uri : OPERATION FAILED",1);
109
+
110
+		return false;
111
+	}
112
+
113
+
114
+	public function purgeJobs()
115
+	{
116
+		$this->jobs = array_merge($this->jobs,array(""));
117
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
118
+
119
+		self::_setOperationId();
120
+		$this->parsed = array();
121
+		unset($this->printer_attributes);
122
+
123
+		if (!isset($this->setup->uri))
124
+		{
125
+			$this->getPrinters();
126
+			unset($this->jobs[count($this->jobs) - 1]);
127
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
128
+			unset($this->status[count($this->status) - 1]);
129
+
130
+			if (array_key_exists(0,$this->available_printers))
131
+			{
132
+			   self::setPrinterURI($this->available_printers[0]);
133
+			}
134
+			else
135
+			{
136
+				trigger_error(_("purgeJobs: Printer URI is not set: die"),E_USER_WARNING);
137
+				self::_putDebug( _("purgeJobs: Printer URI is not set: die\n"));
138
+				self::_errorLog("purgeJobs: Printer URI is not set, die",2);
139
+				return FALSE;
140
+				}
141
+			}
142
+
143
+		if (!isset($this->setup->charset))
144
+		{
145
+			self::setCharset();
146
+		}
147
+
148
+		if (!isset($this->setup->language))
149
+		{
150
+			self::setLanguage('en_us');
151
+		}
152
+
153
+		if (!isset($this->meta->username))
154
+		{
155
+			self::setUserName();
156
+		}
157
+
158
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
159
+						 . chr(0x00) . chr (0x12) // purge-Jobs | operation-id
160
+						 . $this->meta->operation_id //           request-id
161
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
162
+						 . $this->meta->charset
163
+						 . $this->meta->language
164
+						 . $this->meta->printer_uri
165
+						 . $this->meta->username
166
+						 . chr(0x22)
167
+						 . self::_giveMeStringLength("purge-jobs")
168
+						 . "purge-jobs"
169
+						 . self::_giveMeStringLength(chr(0x01))
170
+						 . chr(0x01)
171
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
172
+
173
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
174
+
175
+		self::_putDebug(sprintf(_("purging jobs of %s\n"),$this->printer_uri)); 
176
+
177
+		$this->output = $this->stringjob;
178
+
179
+		$post_values = array( "Content-Type"=>"application/ipp",
180
+							  "Data"=>$this->output);
181
+
182
+		if (self::_sendHttp ($post_values,$this->paths['admin']))
183
+		{
184
+			self::_parseServerOutput();
185
+			self::_parseAttributes();
186
+			}
187
+
188
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
189
+		{
190
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
191
+
192
+			if ($this->serveroutput->status == "successfull-ok")
193
+			{
194
+				self::_errorLog(sprintf(_("purging jobs of %s: "),$this->printer_uri)
195
+							.$this->serveroutput->status,3);
196
+			}
197
+			else
198
+			{
199
+				 self::_errorLog(sprintf(_("purging jobs of %s: "),$this->printer_uri)
200
+											 .$this->serveroutput->status,1);
201
+			}
202
+
203
+			return $this->serveroutput->status; 
204
+		}
205
+
206
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
207
+		self::_errorLog(date("Y-m-d H:i:s : ")
208
+						.basename($_SERVER['PHP_SELF'])
209
+						.sprintf(_("purging jobs of %s : OPERATION FAILED"),
210
+									 $this->printer_uri),3);
211
+
212
+		return false;
213
+	}
214
+
215
+	public function createJob()
216
+	{
217
+		self::_setOperationId();
218
+		$this->parsed = array();
219
+		unset($this->printer_attributes);
220
+
221
+		if (!isset($this->setup->uri))
222
+		{
223
+			$this->getPrinters();
224
+			unset($this->jobs[count($this->jobs) - 1]);
225
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
226
+			unset($this->status[count($this->status) - 1]);
227
+
228
+			if (array_key_exists(0,$this->available_printers))
229
+			{
230
+			   self::setPrinterURI($this->available_printers[0]);
231
+			}
232
+			else
233
+			{
234
+				trigger_error(_("createJob: Printer URI is not set: die"),E_USER_WARNING);
235
+				self::_putDebug( _("createJob: Printer URI is not set: die\n"));
236
+				self::_errorLog("createJob: Printer URI is not set, die",2);
237
+				return FALSE;
238
+				}
239
+			}
240
+
241
+		if (!isset($this->setup->charset))
242
+		{
243
+			self::setCharset();
244
+		}
245
+
246
+		if (!isset($this->setup->language))
247
+		{
248
+			self::setLanguage('en_us');
249
+		}
250
+
251
+		if (!isset($this->meta->username))
252
+		{
253
+			self::setUserName();
254
+		}
255
+
256
+		if (!isset($this->setup->copies))
257
+		{
258
+			self::setCopies(1);
259
+		}
260
+
261
+		if (!isset($this->meta->fidelity))
262
+		{
263
+			$this->meta->fidelity = '';
264
+		}
265 265
  
266
-        if (!isset($this->meta->sides))
267
-        {
268
-            $this->meta->sides = '';
269
-        }
270
-
271
-        if (!isset($this->meta->page_ranges))
272
-        {
273
-            $this->meta->page_ranges = '';
274
-        }
275
-
276
-        if (!isset($this->setup->jobname))
277
-        {
278
-            if (is_readable($this->data))
279
-            {
280
-                self::setJobName(basename($this->data),true);
281
-            }
282
-            else
283
-            {
284
-                self::setJobName();
285
-            }
286
-        }
287
-        unset($this->setup->jobname);
288
-
289
-        if (!isset($this->timeout))
290
-        {
291
-            $this->timeout = 60;
292
-        }
293
-
294
-        $timeout = self::_integerBuild($this->timeout);
266
+		if (!isset($this->meta->sides))
267
+		{
268
+			$this->meta->sides = '';
269
+		}
270
+
271
+		if (!isset($this->meta->page_ranges))
272
+		{
273
+			$this->meta->page_ranges = '';
274
+		}
275
+
276
+		if (!isset($this->setup->jobname))
277
+		{
278
+			if (is_readable($this->data))
279
+			{
280
+				self::setJobName(basename($this->data),true);
281
+			}
282
+			else
283
+			{
284
+				self::setJobName();
285
+			}
286
+		}
287
+		unset($this->setup->jobname);
288
+
289
+		if (!isset($this->timeout))
290
+		{
291
+			$this->timeout = 60;
292
+		}
293
+
294
+		$timeout = self::_integerBuild($this->timeout);
295 295
         
296
-        $this->meta->timeout = chr(0x21) // integer
297
-                             . self::_giveMeStringLength("multiple-operation-time-out")
298
-                             . "multiple-operation-time-out"
299
-                             . self::_giveMeStringLength($timeout)
300
-                             . $timeout;
301
-
302
-        $jobattributes = '';
303
-        $operationattributes = '';
304
-        $printerattributes = '';
305
-        self::_buildValues($operationattributes,$jobattributes,$printerattributes);
306
-
307
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
308
-                         . chr(0x00) . chr (0x05) // Create-Job | operation-id
309
-                         . $this->meta->operation_id //           request-id
310
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
311
-                         . $this->meta->charset
312
-                         . $this->meta->language
313
-                         . $this->meta->printer_uri
314
-                         . $this->meta->username
315
-                         . $this->meta->jobname
316
-                         . $this->meta->fidelity
317
-                         . $this->meta->timeout
318
-                         . $operationattributes
319
-                         . chr(0x02) // start job-attributes | job-attributes-tag
320
-                         . $this->meta->copies
321
-                         . $this->meta->sides
322
-                         . $this->meta->page_ranges
323
-                         . $jobattributes
324
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
325
-
326
-        unset ($this->meta->copies,$this->meta->sides,$this->meta->page_ranges);
327
-
328
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
329
-
330
-        self::_putDebug(sprintf(_("creating job %s, printer %s\n"),$this->last_job,$this->printer_uri)); 
331
-
332
-        $this->output = $this->stringjob;
333
-
334
-        $post_values = array( "Content-Type"=>"application/ipp",
335
-                              "Data"=>$this->output);
336
-
337
-        if (self::_sendHttp ($post_values,$this->paths['printers']))
338
-        {
339
-            if(self::_parseServerOutput())
340
-            {
341
-                $this->_getJobId();
342
-                $this->_getJobUri();
343
-                $this->_parseJobAttributes();
344
-            }
345
-            else
346
-            {
347
-                $this->jobs = array_merge($this->jobs,array(''));
348
-                $this->jobs_uri = array_merge($this->jobs_uri,array(''));
349
-            }
350
-        }
351
-
352
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
353
-        {
354
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
355
-
356
-            if ($this->serveroutput->status == "successfull-ok")
357
-            {
358
-                self::_errorLog(sprintf(_("Create job: job %s"),$this->last_job)
359
-                            .$this->serveroutput->status,3);
360
-            }
361
-            else
362
-            {
363
-
364
-                $this->jobs = array_merge($this->jobs,array(""));
365
-                $this->jobs_uri = array_merge($this->jobs_uri,array(""));
366
-                self::_errorLog(sprintf(_("Create-Job: %s"),$this->serveroutput->status),1);
367
-                }                             
368
-            return $this->serveroutput->status; 
369
-            }    
370
-
371
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
372
-        self::_errorLog(date("Y-m-d H:i:s : ")
373
-                        .basename($_SERVER['PHP_SELF'])
374
-                        .sprintf(_("Creating job on %s : OPERATION FAILED"),
375
-                                     $this->printer_uri),3);
376
-
377
-        $this->jobs = array_merge($this->jobs,array(""));
378
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
379
-        return false;
380
-    }
381
-
382
-    public function sendDocument($job,$is_last=false)
383
-    {
384
-        self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
385
-
386
-        if (!$this->_stringDocument($job,$is_last))
387
-        {
388
-            return FALSE;
389
-        }
390
-
391
-        if (is_readable($this->data))
392
-        {
393
-            self::_putDebug( _("sending Document\n")); 
394
-
395
-            $this->output = $this->stringjob;
396
-
397
-            if ($this->setup->datatype == "TEXT")
398
-            {
399
-                $this->output .= chr(0x16);
400
-            } // ASCII "SYN"
401
-
402
-            $post_values = array( "Content-Type" => "application/ipp",
403
-                                  "Data" => $this->output,
404
-                                  "File" => $this->data);
405
-
406
-            if ($this->setup->datatype == "TEXT" && !isset($this->setup->noFormFeed))
407
-            {
408
-                $post_values = array_merge($post_values,array("Filetype"=>"TEXT"));
409
-            }
410
-        }
411
-        else
412
-        {
413
-            self::_putDebug( _("sending DATA as document\n")); 
414
-
415
-            $this->output = $this->stringjob;
416
-            $this->output .= $this->datahead;    
417
-            $this->output .= $this->data;
418
-            $this->output .= $this->datatail;
419
-
420
-            $post_values = array( "Content-Type" => "application/ipp",
421
-                                  "Data" => $this->output);
422
-        }
423
-
424
-        if (self::_sendHttp ($post_values,$this->paths['printers']))
425
-        {
426
-
427
-            if(self::_parseServerOutput())
428
-            {
429
-                $this->_getJobId();
430
-                //$this->_getPrinterUri();
431
-                $this->_getJobUri();
432
-                $this->_parseJobAttributes();
433
-            }
434
-            else
435
-            {
436
-                $this->jobs = array_merge($this->jobs,array($job));
437
-                $this->jobs_uri = array_merge($this->jobs_uri,array($job));
438
-                }
439
-            }
296
+		$this->meta->timeout = chr(0x21) // integer
297
+							 . self::_giveMeStringLength("multiple-operation-time-out")
298
+							 . "multiple-operation-time-out"
299
+							 . self::_giveMeStringLength($timeout)
300
+							 . $timeout;
301
+
302
+		$jobattributes = '';
303
+		$operationattributes = '';
304
+		$printerattributes = '';
305
+		self::_buildValues($operationattributes,$jobattributes,$printerattributes);
306
+
307
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
308
+						 . chr(0x00) . chr (0x05) // Create-Job | operation-id
309
+						 . $this->meta->operation_id //           request-id
310
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
311
+						 . $this->meta->charset
312
+						 . $this->meta->language
313
+						 . $this->meta->printer_uri
314
+						 . $this->meta->username
315
+						 . $this->meta->jobname
316
+						 . $this->meta->fidelity
317
+						 . $this->meta->timeout
318
+						 . $operationattributes
319
+						 . chr(0x02) // start job-attributes | job-attributes-tag
320
+						 . $this->meta->copies
321
+						 . $this->meta->sides
322
+						 . $this->meta->page_ranges
323
+						 . $jobattributes
324
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
325
+
326
+		unset ($this->meta->copies,$this->meta->sides,$this->meta->page_ranges);
327
+
328
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
329
+
330
+		self::_putDebug(sprintf(_("creating job %s, printer %s\n"),$this->last_job,$this->printer_uri)); 
331
+
332
+		$this->output = $this->stringjob;
333
+
334
+		$post_values = array( "Content-Type"=>"application/ipp",
335
+							  "Data"=>$this->output);
336
+
337
+		if (self::_sendHttp ($post_values,$this->paths['printers']))
338
+		{
339
+			if(self::_parseServerOutput())
340
+			{
341
+				$this->_getJobId();
342
+				$this->_getJobUri();
343
+				$this->_parseJobAttributes();
344
+			}
345
+			else
346
+			{
347
+				$this->jobs = array_merge($this->jobs,array(''));
348
+				$this->jobs_uri = array_merge($this->jobs_uri,array(''));
349
+			}
350
+		}
351
+
352
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
353
+		{
354
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
355
+
356
+			if ($this->serveroutput->status == "successfull-ok")
357
+			{
358
+				self::_errorLog(sprintf(_("Create job: job %s"),$this->last_job)
359
+							.$this->serveroutput->status,3);
360
+			}
361
+			else
362
+			{
363
+
364
+				$this->jobs = array_merge($this->jobs,array(""));
365
+				$this->jobs_uri = array_merge($this->jobs_uri,array(""));
366
+				self::_errorLog(sprintf(_("Create-Job: %s"),$this->serveroutput->status),1);
367
+				}                             
368
+			return $this->serveroutput->status; 
369
+			}    
370
+
371
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
372
+		self::_errorLog(date("Y-m-d H:i:s : ")
373
+						.basename($_SERVER['PHP_SELF'])
374
+						.sprintf(_("Creating job on %s : OPERATION FAILED"),
375
+									 $this->printer_uri),3);
376
+
377
+		$this->jobs = array_merge($this->jobs,array(""));
378
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
379
+		return false;
380
+	}
381
+
382
+	public function sendDocument($job,$is_last=false)
383
+	{
384
+		self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
385
+
386
+		if (!$this->_stringDocument($job,$is_last))
387
+		{
388
+			return FALSE;
389
+		}
390
+
391
+		if (is_readable($this->data))
392
+		{
393
+			self::_putDebug( _("sending Document\n")); 
394
+
395
+			$this->output = $this->stringjob;
396
+
397
+			if ($this->setup->datatype == "TEXT")
398
+			{
399
+				$this->output .= chr(0x16);
400
+			} // ASCII "SYN"
401
+
402
+			$post_values = array( "Content-Type" => "application/ipp",
403
+								  "Data" => $this->output,
404
+								  "File" => $this->data);
405
+
406
+			if ($this->setup->datatype == "TEXT" && !isset($this->setup->noFormFeed))
407
+			{
408
+				$post_values = array_merge($post_values,array("Filetype"=>"TEXT"));
409
+			}
410
+		}
411
+		else
412
+		{
413
+			self::_putDebug( _("sending DATA as document\n")); 
414
+
415
+			$this->output = $this->stringjob;
416
+			$this->output .= $this->datahead;    
417
+			$this->output .= $this->data;
418
+			$this->output .= $this->datatail;
419
+
420
+			$post_values = array( "Content-Type" => "application/ipp",
421
+								  "Data" => $this->output);
422
+		}
423
+
424
+		if (self::_sendHttp ($post_values,$this->paths['printers']))
425
+		{
426
+
427
+			if(self::_parseServerOutput())
428
+			{
429
+				$this->_getJobId();
430
+				//$this->_getPrinterUri();
431
+				$this->_getJobUri();
432
+				$this->_parseJobAttributes();
433
+			}
434
+			else
435
+			{
436
+				$this->jobs = array_merge($this->jobs,array($job));
437
+				$this->jobs_uri = array_merge($this->jobs_uri,array($job));
438
+				}
439
+			}
440 440
         
441
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
442
-        {
443
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
444
-
445
-            if ($this->serveroutput->status == "successfull-ok")
446
-            {
447
-                self::_errorLog(sprintf("sending document, job %s: %s",$job,$this->serveroutput->status),3);
448
-            }
449
-            else
450
-            {
451
-                $this->jobs = array_merge($this->jobs,array(""));
452
-                $this->jobs_uri = array_merge($this->jobs_uri,array(""));
453
-                self::_errorLog(sprintf("sending document, job %s: %s",$job,$this->serveroutput->status),1);
454
-            }
455
-            return $this->serveroutput->status; 
456
-        }
457
-
458
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
459
-        $this->jobs = array_merge($this->jobs,array($job));
460
-        $this->jobs_uri = array_merge($this->jobs_uri,array($job));
461
-        self::_errorLog(sprintf("sending document, job %s : OPERATION FAILED",$job),1);
462
-
463
-        return false;
464
-    }
465
-
466
-
467
-    public function sendURI ($uri,$job,$is_last=false)
468
-    {
469
-        self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
470
-
471
-        if (!$this->_stringSendUri($uri,$job,$is_last))
472
-        {
473
-            return FALSE;
474
-        }
475
-
476
-            self::_putDebug( _("sending URI $uri\n")); 
477
-
478
-            $this->output = $this->stringjob;
479
-
480
-            $post_values = array( "Content-Type" => "application/ipp",
481
-                                  "Data" => $this->output);
482
-
483
-        if (self::_sendHttp ($post_values,$this->paths['printers']))
484
-        {
485
-            if(self::_parseServerOutput())
486
-            {
487
-                $this->_getJobId();
488
-                //$this->_getPrinterUri();
489
-                $this->_getJobUri();
490
-                $this->_parseJobAttributes();
491
-            }
492
-            else
493
-            {
494
-                $this->jobs = array_merge($this->jobs,array($job));
495
-                $this->jobs_uri = array_merge($this->jobs_uri,array($job));
496
-                }
497
-            }
498
-
499
-        $this->attributes = &$this->job_attributes;
500
-
501
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
502
-        {
503
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
504
-
505
-            if ($this->serveroutput->status == "successfull-ok")
506
-            {
507
-                self::_errorLog(sprintf("sending uri %s, job %s: %s",$uri,$job,$this->serveroutput->status),3);
508
-            }
509
-            else
510
-            {
511
-                $this->jobs = array_merge($this->jobs,array(""));
512
-                $this->jobs_uri = array_merge($this->jobs_uri,array(""));
513
-                self::_errorLog(sprintf("sending uri, job %s: %s",$uri,$job,$this->serveroutput->status),1);
514
-            }
515
-            return $this->serveroutput->status; 
516
-        }
517
-
518
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
519
-        $this->jobs = array_merge($this->jobs,array($job));
520
-        $this->jobs_uri = array_merge($this->jobs_uri,array($job));
521
-        self::_errorLog(sprintf("sending uri %s, job %s : OPERATION FAILED",$uri,$job),1);
522
-
523
-        return false;
524
-    }
525
-
526
-
527
-    public function pausePrinter()
528
-    {
529
-        $this->jobs = array_merge($this->jobs,array(""));
530
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
531
-
532
-        self::_setOperationId();
533
-        $this->parsed = array();
534
-        unset($this->printer_attributes);
535
-
536
-        if (!isset($this->setup->uri))
537
-        {
538
-            $this->getPrinters();
539
-            unset($this->jobs[count($this->jobs) - 1]);
540
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
541
-            unset($this->status[count($this->status) - 1]);
542
-
543
-            if (array_key_exists(0,$this->available_printers))
544
-            {
545
-               self::setPrinterURI($this->available_printers[0]);
546
-            }
547
-            else
548
-            {
549
-                trigger_error(_("pausePrinter: Printer URI is not set: die"),E_USER_WARNING);
550
-                self::_putDebug( _("pausePrinter: Printer URI is not set: die\n"));
551
-                self::_errorLog("pausePrinter: Printer URI is not set, die",2);
552
-                return FALSE;
553
-            }
554
-        }
555
-
556
-        if (!isset($this->setup->charset))
557
-        {
558
-            self::setCharset();
559
-        }
560
-
561
-        if (!isset($this->setup->language))
562
-        {
563
-            self::setLanguage('en_us');
564
-        }
565
-
566
-        if (!isset($this->meta->username))
567
-        {
568
-            self::setUserName();
569
-        }
570
-
571
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
572
-                         . chr(0x00) . chr (0x10) // Pause-Printer | operation-id
573
-                         . $this->meta->operation_id //           request-id
574
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
575
-                         . $this->meta->charset
576
-                         . $this->meta->language
577
-                         . $this->meta->printer_uri
578
-                         . $this->meta->username
579
-                         /* . chr(0x22)
441
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
442
+		{
443
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
444
+
445
+			if ($this->serveroutput->status == "successfull-ok")
446
+			{
447
+				self::_errorLog(sprintf("sending document, job %s: %s",$job,$this->serveroutput->status),3);
448
+			}
449
+			else
450
+			{
451
+				$this->jobs = array_merge($this->jobs,array(""));
452
+				$this->jobs_uri = array_merge($this->jobs_uri,array(""));
453
+				self::_errorLog(sprintf("sending document, job %s: %s",$job,$this->serveroutput->status),1);
454
+			}
455
+			return $this->serveroutput->status; 
456
+		}
457
+
458
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
459
+		$this->jobs = array_merge($this->jobs,array($job));
460
+		$this->jobs_uri = array_merge($this->jobs_uri,array($job));
461
+		self::_errorLog(sprintf("sending document, job %s : OPERATION FAILED",$job),1);
462
+
463
+		return false;
464
+	}
465
+
466
+
467
+	public function sendURI ($uri,$job,$is_last=false)
468
+	{
469
+		self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
470
+
471
+		if (!$this->_stringSendUri($uri,$job,$is_last))
472
+		{
473
+			return FALSE;
474
+		}
475
+
476
+			self::_putDebug( _("sending URI $uri\n")); 
477
+
478
+			$this->output = $this->stringjob;
479
+
480
+			$post_values = array( "Content-Type" => "application/ipp",
481
+								  "Data" => $this->output);
482
+
483
+		if (self::_sendHttp ($post_values,$this->paths['printers']))
484
+		{
485
+			if(self::_parseServerOutput())
486
+			{
487
+				$this->_getJobId();
488
+				//$this->_getPrinterUri();
489
+				$this->_getJobUri();
490
+				$this->_parseJobAttributes();
491
+			}
492
+			else
493
+			{
494
+				$this->jobs = array_merge($this->jobs,array($job));
495
+				$this->jobs_uri = array_merge($this->jobs_uri,array($job));
496
+				}
497
+			}
498
+
499
+		$this->attributes = &$this->job_attributes;
500
+
501
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
502
+		{
503
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
504
+
505
+			if ($this->serveroutput->status == "successfull-ok")
506
+			{
507
+				self::_errorLog(sprintf("sending uri %s, job %s: %s",$uri,$job,$this->serveroutput->status),3);
508
+			}
509
+			else
510
+			{
511
+				$this->jobs = array_merge($this->jobs,array(""));
512
+				$this->jobs_uri = array_merge($this->jobs_uri,array(""));
513
+				self::_errorLog(sprintf("sending uri, job %s: %s",$uri,$job,$this->serveroutput->status),1);
514
+			}
515
+			return $this->serveroutput->status; 
516
+		}
517
+
518
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
519
+		$this->jobs = array_merge($this->jobs,array($job));
520
+		$this->jobs_uri = array_merge($this->jobs_uri,array($job));
521
+		self::_errorLog(sprintf("sending uri %s, job %s : OPERATION FAILED",$uri,$job),1);
522
+
523
+		return false;
524
+	}
525
+
526
+
527
+	public function pausePrinter()
528
+	{
529
+		$this->jobs = array_merge($this->jobs,array(""));
530
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
531
+
532
+		self::_setOperationId();
533
+		$this->parsed = array();
534
+		unset($this->printer_attributes);
535
+
536
+		if (!isset($this->setup->uri))
537
+		{
538
+			$this->getPrinters();
539
+			unset($this->jobs[count($this->jobs) - 1]);
540
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
541
+			unset($this->status[count($this->status) - 1]);
542
+
543
+			if (array_key_exists(0,$this->available_printers))
544
+			{
545
+			   self::setPrinterURI($this->available_printers[0]);
546
+			}
547
+			else
548
+			{
549
+				trigger_error(_("pausePrinter: Printer URI is not set: die"),E_USER_WARNING);
550
+				self::_putDebug( _("pausePrinter: Printer URI is not set: die\n"));
551
+				self::_errorLog("pausePrinter: Printer URI is not set, die",2);
552
+				return FALSE;
553
+			}
554
+		}
555
+
556
+		if (!isset($this->setup->charset))
557
+		{
558
+			self::setCharset();
559
+		}
560
+
561
+		if (!isset($this->setup->language))
562
+		{
563
+			self::setLanguage('en_us');
564
+		}
565
+
566
+		if (!isset($this->meta->username))
567
+		{
568
+			self::setUserName();
569
+		}
570
+
571
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
572
+						 . chr(0x00) . chr (0x10) // Pause-Printer | operation-id
573
+						 . $this->meta->operation_id //           request-id
574
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
575
+						 . $this->meta->charset
576
+						 . $this->meta->language
577
+						 . $this->meta->printer_uri
578
+						 . $this->meta->username
579
+						 /* . chr(0x22)
580 580
                          . self::_giveMeStringLength("purge-jobs")
581 581
                          . "purge-jobs"
582 582
                          . self::_giveMeStringLength(chr(0x01))
583 583
                          . chr(0x01) */
584
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
585
-
586
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
587
-
588
-        self::_putDebug(sprintf(_("pause printer %s\n"),$this->printer_uri)); 
589
-
590
-        $this->output = $this->stringjob;
591
-
592
-        $post_values = array( "Content-Type"=>"application/ipp",
593
-                              "Data"=>$this->output);
594
-
595
-        if (self::_sendHttp ($post_values,$this->paths['admin']))
596
-        {
597
-            self::_parseServerOutput();
598
-            self::_parseAttributes();
599
-        }
600
-
601
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
602
-        {
603
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
604
-
605
-            if ($this->serveroutput->status == "successfull-ok")
606
-            {
607
-                self::_errorLog(sprintf(_("Pause printer %s: "),$this->printer_uri)
608
-                            .$this->serveroutput->status,3);
609
-            }
610
-            else
611
-            {
612
-                 self::_errorLog(sprintf(_("pause printer %s: "),$this->printer_uri)
613
-                                             .$this->serveroutput->status,1);
614
-            }
615
-
616
-            return $this->serveroutput->status; 
617
-        }
618
-
619
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
620
-        self::_errorLog(date("Y-m-d H:i:s : ")
621
-                        .basename($_SERVER['PHP_SELF'])
622
-                        .sprintf(_("pause printer %s : OPERATION FAILED"),
623
-                                     $this->printer_uri),3);
624
-
625
-        return false;
626
-    }
627
-
628
-
629
-    public function resumePrinter()
630
-    {
631
-        $this->jobs = array_merge($this->jobs,array(""));
632
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
633
-
634
-        self::_setOperationId();
635
-        $this->parsed = array();
636
-        unset($this->printer_attributes);
637
-
638
-        if (!isset($this->setup->uri))
639
-        {
640
-            $this->getPrinters();
641
-            unset($this->jobs[count($this->jobs) - 1]);
642
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
643
-            unset($this->status[count($this->status) - 1]);
644
-
645
-            if (array_key_exists(0,$this->available_printers))
646
-            {
647
-               self::setPrinterURI($this->available_printers[0]);
648
-            }
649
-            else
650
-            {
651
-                trigger_error(_("resumePrinter: Printer URI is not set: die"),E_USER_WARNING);
652
-                self::_putDebug( _("resumePrinter: Printer URI is not set: die\n"));
653
-                self::_errorLog(" Printer URI is not set, die",2);
654
-                return FALSE;
655
-            }
656
-        }
657
-
658
-        if (!isset($this->setup->charset))
659
-        {
660
-            self::setCharset();
661
-        }
662
-
663
-        if (!isset($this->setup->language))
664
-        {
665
-            self::setLanguage('en_us');
666
-        }
667
-
668
-        if (!isset($this->meta->username))
669
-        {
670
-            self::setUserName();
671
-        }
672
-
673
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
674
-                         . chr(0x00) . chr (0x11) // suse-Printer | operation-id
675
-                         . $this->meta->operation_id //           request-id
676
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
677
-                         . $this->meta->charset
678
-                         . $this->meta->language
679
-                         . $this->meta->printer_uri
680
-                         . $this->meta->username
681
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
682
-
683
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
684
-
685
-        self::_putDebug(sprintf(_("resume printer %s\n"),$this->printer_uri)); 
686
-
687
-        $this->output = $this->stringjob;
688
-
689
-        $post_values = array( "Content-Type"=>"application/ipp",
690
-                              "Data"=>$this->output);
691
-
692
-        if (self::_sendHttp ($post_values,$this->paths['admin']))
693
-        {
694
-            self::_parseServerOutput();
695
-            self::_parseAttributes();
696
-        }
697
-
698
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
699
-        {
700
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
701
-
702
-            if ($this->serveroutput->status == "successfull-ok")
703
-            {
704
-                self::_errorLog(sprintf(_("resume printer %s: "),$this->printer_uri)
705
-                            .$this->serveroutput->status,3);
706
-            }
707
-            else
708
-            {
709
-                 self::_errorLog(sprintf(_("resume printer %s: "),$this->printer_uri)
710
-                                             .$this->serveroutput->status,1);
711
-            }
712
-
713
-            return $this->serveroutput->status; 
714
-        }
715
-
716
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
717
-        self::_errorLog(date("Y-m-d H:i:s : ")
718
-                        .basename($_SERVER['PHP_SELF'])
719
-                        .sprintf(_("resume printer %s : OPERATION FAILED"),
720
-                                     $this->printer_uri),3);
721
-
722
-        return false;
723
-    }
724
-
725
-
726
-    public function holdJob ($job_uri,$until='indefinite')
727
-    {
728
-        $this->jobs = array_merge($this->jobs,array(""));
729
-        $this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
730
-
731
-        self::_setOperationId();
732
-        $this->parsed = array();
733
-        unset($this->printer_attributes);
734
-
735
-        if (!isset($this->setup->charset))
736
-        {
737
-            self::setCharset();
738
-        }
739
-
740
-        if (!isset($this->setup->language))
741
-        {
742
-            self::setLanguage('en_us');
743
-        }
744
-
745
-        if (!isset($this->meta->username))
746
-        {
747
-            self::setUserName();
748
-        }
749
-
750
-        if (!isset($this->meta->message))
751
-        {
752
-            $this->meta->message = '';
753
-        }
754
-
755
-        self::_setJobUri($job_uri);
584
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
585
+
586
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
587
+
588
+		self::_putDebug(sprintf(_("pause printer %s\n"),$this->printer_uri)); 
589
+
590
+		$this->output = $this->stringjob;
591
+
592
+		$post_values = array( "Content-Type"=>"application/ipp",
593
+							  "Data"=>$this->output);
594
+
595
+		if (self::_sendHttp ($post_values,$this->paths['admin']))
596
+		{
597
+			self::_parseServerOutput();
598
+			self::_parseAttributes();
599
+		}
600
+
601
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
602
+		{
603
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
604
+
605
+			if ($this->serveroutput->status == "successfull-ok")
606
+			{
607
+				self::_errorLog(sprintf(_("Pause printer %s: "),$this->printer_uri)
608
+							.$this->serveroutput->status,3);
609
+			}
610
+			else
611
+			{
612
+				 self::_errorLog(sprintf(_("pause printer %s: "),$this->printer_uri)
613
+											 .$this->serveroutput->status,1);
614
+			}
615
+
616
+			return $this->serveroutput->status; 
617
+		}
618
+
619
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
620
+		self::_errorLog(date("Y-m-d H:i:s : ")
621
+						.basename($_SERVER['PHP_SELF'])
622
+						.sprintf(_("pause printer %s : OPERATION FAILED"),
623
+									 $this->printer_uri),3);
624
+
625
+		return false;
626
+	}
627
+
628
+
629
+	public function resumePrinter()
630
+	{
631
+		$this->jobs = array_merge($this->jobs,array(""));
632
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
633
+
634
+		self::_setOperationId();
635
+		$this->parsed = array();
636
+		unset($this->printer_attributes);
637
+
638
+		if (!isset($this->setup->uri))
639
+		{
640
+			$this->getPrinters();
641
+			unset($this->jobs[count($this->jobs) - 1]);
642
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
643
+			unset($this->status[count($this->status) - 1]);
644
+
645
+			if (array_key_exists(0,$this->available_printers))
646
+			{
647
+			   self::setPrinterURI($this->available_printers[0]);
648
+			}
649
+			else
650
+			{
651
+				trigger_error(_("resumePrinter: Printer URI is not set: die"),E_USER_WARNING);
652
+				self::_putDebug( _("resumePrinter: Printer URI is not set: die\n"));
653
+				self::_errorLog(" Printer URI is not set, die",2);
654
+				return FALSE;
655
+			}
656
+		}
657
+
658
+		if (!isset($this->setup->charset))
659
+		{
660
+			self::setCharset();
661
+		}
662
+
663
+		if (!isset($this->setup->language))
664
+		{
665
+			self::setLanguage('en_us');
666
+		}
667
+
668
+		if (!isset($this->meta->username))
669
+		{
670
+			self::setUserName();
671
+		}
672
+
673
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
674
+						 . chr(0x00) . chr (0x11) // suse-Printer | operation-id
675
+						 . $this->meta->operation_id //           request-id
676
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
677
+						 . $this->meta->charset
678
+						 . $this->meta->language
679
+						 . $this->meta->printer_uri
680
+						 . $this->meta->username
681
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
682
+
683
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
684
+
685
+		self::_putDebug(sprintf(_("resume printer %s\n"),$this->printer_uri)); 
686
+
687
+		$this->output = $this->stringjob;
688
+
689
+		$post_values = array( "Content-Type"=>"application/ipp",
690
+							  "Data"=>$this->output);
691
+
692
+		if (self::_sendHttp ($post_values,$this->paths['admin']))
693
+		{
694
+			self::_parseServerOutput();
695
+			self::_parseAttributes();
696
+		}
697
+
698
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
699
+		{
700
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
701
+
702
+			if ($this->serveroutput->status == "successfull-ok")
703
+			{
704
+				self::_errorLog(sprintf(_("resume printer %s: "),$this->printer_uri)
705
+							.$this->serveroutput->status,3);
706
+			}
707
+			else
708
+			{
709
+				 self::_errorLog(sprintf(_("resume printer %s: "),$this->printer_uri)
710
+											 .$this->serveroutput->status,1);
711
+			}
712
+
713
+			return $this->serveroutput->status; 
714
+		}
715
+
716
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
717
+		self::_errorLog(date("Y-m-d H:i:s : ")
718
+						.basename($_SERVER['PHP_SELF'])
719
+						.sprintf(_("resume printer %s : OPERATION FAILED"),
720
+									 $this->printer_uri),3);
721
+
722
+		return false;
723
+	}
724
+
725
+
726
+	public function holdJob ($job_uri,$until='indefinite')
727
+	{
728
+		$this->jobs = array_merge($this->jobs,array(""));
729
+		$this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
730
+
731
+		self::_setOperationId();
732
+		$this->parsed = array();
733
+		unset($this->printer_attributes);
734
+
735
+		if (!isset($this->setup->charset))
736
+		{
737
+			self::setCharset();
738
+		}
739
+
740
+		if (!isset($this->setup->language))
741
+		{
742
+			self::setLanguage('en_us');
743
+		}
744
+
745
+		if (!isset($this->meta->username))
746
+		{
747
+			self::setUserName();
748
+		}
749
+
750
+		if (!isset($this->meta->message))
751
+		{
752
+			$this->meta->message = '';
753
+		}
754
+
755
+		self::_setJobUri($job_uri);
756 756
         
757
-        $until_strings = array('no-hold','day-time','evening','night','weekend','second-shift','third-shift');
758
-        if (in_array($until,$until_strings))
759
-        {
760
-            true;
761
-        }
762
-        else 
763
-        {
764
-            $until = 'indefinite';
765
-        }
766
-
767
-        $this->meta->job_hold_until = chr(0x42) // keyword
768
-                                    . self::_giveMeStringLength('job-hold-until')
769
-                                    . 'job-hold-until'
770
-                                    . self::_giveMeStringLength($until)
771
-                                    . $until;
772
-
773
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
774
-                         . chr(0x00) . chr (0x0C) // Hold-Job | operation-id
775
-                         . $this->meta->operation_id //           request-id
776
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
777
-                         . $this->meta->charset
778
-                         . $this->meta->language
779
-                         . $this->meta->username
780
-                         . $this->meta->job_uri
781
-                         . $this->meta->message
782
-                         . $this->meta->job_hold_until
783
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
784
-
785
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
786
-
787
-        self::_putDebug(sprintf(_("hold job %s until %s\n"),$job_uri,$until)); 
788
-
789
-        $this->output = $this->stringjob;
790
-
791
-        $post_values = array( "Content-Type"=>"application/ipp",
792
-                              "Data"=>$this->output);
793
-
794
-        if (self::_sendHttp ($post_values,$this->paths['jobs']))
795
-        {
796
-            self::_parseServerOutput();
797
-            self::_parseAttributes();
798
-            }
799
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
800
-        {
757
+		$until_strings = array('no-hold','day-time','evening','night','weekend','second-shift','third-shift');
758
+		if (in_array($until,$until_strings))
759
+		{
760
+			true;
761
+		}
762
+		else 
763
+		{
764
+			$until = 'indefinite';
765
+		}
766
+
767
+		$this->meta->job_hold_until = chr(0x42) // keyword
768
+									. self::_giveMeStringLength('job-hold-until')
769
+									. 'job-hold-until'
770
+									. self::_giveMeStringLength($until)
771
+									. $until;
772
+
773
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
774
+						 . chr(0x00) . chr (0x0C) // Hold-Job | operation-id
775
+						 . $this->meta->operation_id //           request-id
776
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
777
+						 . $this->meta->charset
778
+						 . $this->meta->language
779
+						 . $this->meta->username
780
+						 . $this->meta->job_uri
781
+						 . $this->meta->message
782
+						 . $this->meta->job_hold_until
783
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
784
+
785
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
786
+
787
+		self::_putDebug(sprintf(_("hold job %s until %s\n"),$job_uri,$until)); 
788
+
789
+		$this->output = $this->stringjob;
790
+
791
+		$post_values = array( "Content-Type"=>"application/ipp",
792
+							  "Data"=>$this->output);
793
+
794
+		if (self::_sendHttp ($post_values,$this->paths['jobs']))
795
+		{
796
+			self::_parseServerOutput();
797
+			self::_parseAttributes();
798
+			}
799
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
800
+		{
801 801
             
802
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
802
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
803 803
             
804
-            if ($this->serveroutput->status == "successfull-ok")
805
-            {
806
-                self::_errorLog(sprintf(_("hold job %s until %s: "),$job_uri,$until)
807
-                            .$this->serveroutput->status,3);
808
-            }
809
-            else
810
-            {
811
-                 self::_errorLog(sprintf(_("hold job %s until %s: "),$job_uri,$until)
812
-                                             .$this->serveroutput->status,1);
813
-            }
814
-
815
-            return $this->serveroutput->status; 
816
-        }
817
-
818
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
819
-        self::_errorLog(date("Y-m-d H:i:s : ")
820
-                        .basename($_SERVER['PHP_SELF'])
821
-                        .sprintf(_("hold job %s until %s : OPERATION FAILED"),
822
-                                     $job_uri,$until),3);
823
-
824
-        return false;
825
-    }
804
+			if ($this->serveroutput->status == "successfull-ok")
805
+			{
806
+				self::_errorLog(sprintf(_("hold job %s until %s: "),$job_uri,$until)
807
+							.$this->serveroutput->status,3);
808
+			}
809
+			else
810
+			{
811
+				 self::_errorLog(sprintf(_("hold job %s until %s: "),$job_uri,$until)
812
+											 .$this->serveroutput->status,1);
813
+			}
814
+
815
+			return $this->serveroutput->status; 
816
+		}
817
+
818
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
819
+		self::_errorLog(date("Y-m-d H:i:s : ")
820
+						.basename($_SERVER['PHP_SELF'])
821
+						.sprintf(_("hold job %s until %s : OPERATION FAILED"),
822
+									 $job_uri,$until),3);
823
+
824
+		return false;
825
+	}
826 826
     
827 827
 
828
-    public function releaseJob ($job_uri)
829
-    {
830
-        $this->jobs = array_merge($this->jobs,array(""));
831
-        $this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
832
-
833
-        self::_setOperationId();
834
-        $this->parsed = array();
835
-        unset($this->printer_attributes);
836
-
837
-        if (!isset($this->setup->charset))
838
-        {
839
-            self::setCharset();
840
-        }
841
-
842
-        if (!isset($this->setup->language))
843
-        {
844
-            self::setLanguage('en_us');
845
-        }
846
-
847
-        if (!isset($this->meta->username))
848
-        {
849
-            self::setUserName();
850
-        }
851
-
852
-        if (!isset($this->meta->message))
853
-        {
854
-            $this->meta->message = '';
855
-        }
856
-
857
-        self::_setJobUri($job_uri);
858
-
859
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
860
-                         . chr(0x00) . chr (0x0D) // Hold-Job | operation-id
861
-                         . $this->meta->operation_id //           request-id
862
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
863
-                         . $this->meta->charset
864
-                         . $this->meta->language
865
-                         . $this->meta->job_uri
866
-                         . $this->meta->username
867
-                         . $this->meta->message
868
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
869
-
870
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
871
-
872
-        self::_putDebug(sprintf(_("release job %s\n"),$job_uri)); 
873
-
874
-        $this->output = $this->stringjob;
875
-
876
-        $post_values = array( "Content-Type"=>"application/ipp",
877
-                              "Data"=>$this->output);
878
-
879
-        if (self::_sendHttp ($post_values,$this->paths['jobs']))
880
-        {
881
-            self::_parseServerOutput();
882
-            self::_parseAttributes();
883
-        }
884
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
885
-        {
886
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
828
+	public function releaseJob ($job_uri)
829
+	{
830
+		$this->jobs = array_merge($this->jobs,array(""));
831
+		$this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
832
+
833
+		self::_setOperationId();
834
+		$this->parsed = array();
835
+		unset($this->printer_attributes);
836
+
837
+		if (!isset($this->setup->charset))
838
+		{
839
+			self::setCharset();
840
+		}
841
+
842
+		if (!isset($this->setup->language))
843
+		{
844
+			self::setLanguage('en_us');
845
+		}
846
+
847
+		if (!isset($this->meta->username))
848
+		{
849
+			self::setUserName();
850
+		}
851
+
852
+		if (!isset($this->meta->message))
853
+		{
854
+			$this->meta->message = '';
855
+		}
856
+
857
+		self::_setJobUri($job_uri);
858
+
859
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
860
+						 . chr(0x00) . chr (0x0D) // Hold-Job | operation-id
861
+						 . $this->meta->operation_id //           request-id
862
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
863
+						 . $this->meta->charset
864
+						 . $this->meta->language
865
+						 . $this->meta->job_uri
866
+						 . $this->meta->username
867
+						 . $this->meta->message
868
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
869
+
870
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
871
+
872
+		self::_putDebug(sprintf(_("release job %s\n"),$job_uri)); 
873
+
874
+		$this->output = $this->stringjob;
875
+
876
+		$post_values = array( "Content-Type"=>"application/ipp",
877
+							  "Data"=>$this->output);
878
+
879
+		if (self::_sendHttp ($post_values,$this->paths['jobs']))
880
+		{
881
+			self::_parseServerOutput();
882
+			self::_parseAttributes();
883
+		}
884
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
885
+		{
886
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
887 887
             
888
-            if ($this->serveroutput->status == "successfull-ok")
889
-            {
890
-                self::_errorLog(sprintf(_("release job %s: "),$job_uri)
891
-                            .$this->serveroutput->status,3);
892
-            }
893
-            else
894
-            {
895
-                 self::_errorLog(sprintf(_("release job %s: "),$job_uri)
896
-                                             .$this->serveroutput->status,1);
897
-            }
898
-
899
-            return $this->serveroutput->status; 
900
-        }
901
-
902
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
903
-        self::_errorLog(date("Y-m-d H:i:s : ")
904
-                        .basename($_SERVER['PHP_SELF'])
905
-                        .sprintf(_("release job %s: OPERATION FAILED"),
906
-                                     $job_uri),3);
907
-
908
-        return false;
909
-    }
910
-
911
-
912
-    public function restartJob ($job_uri)
913
-    {
914
-        $this->jobs = array_merge($this->jobs,array(""));
915
-        $this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
916
-
917
-        self::_setOperationId();
918
-        $this->parsed = array();
919
-        unset($this->printer_attributes);
920
-
921
-        if (!isset($this->setup->charset))
922
-        {
923
-            self::setCharset();
924
-        }
925
-
926
-        if (!isset($this->setup->language))
927
-        {
928
-            self::setLanguage('en_us');
929
-        }
930
-
931
-        if (!isset($this->meta->username))
932
-        {
933
-            self::setUserName();
934
-        }
935
-
936
-        if (!isset($this->meta->message))
937
-        {
938
-            $this->meta->message = '';
939
-        }
940
-
941
-        self::_setJobUri($job_uri);
942
-
943
-        $jobattributes = '';
944
-        $operationattributes = '';
945
-        $printerattributes = '';
946
-        self::_buildValues ($operationattributes,$jobattributes,$printerattributes); 
888
+			if ($this->serveroutput->status == "successfull-ok")
889
+			{
890
+				self::_errorLog(sprintf(_("release job %s: "),$job_uri)
891
+							.$this->serveroutput->status,3);
892
+			}
893
+			else
894
+			{
895
+				 self::_errorLog(sprintf(_("release job %s: "),$job_uri)
896
+											 .$this->serveroutput->status,1);
897
+			}
898
+
899
+			return $this->serveroutput->status; 
900
+		}
901
+
902
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
903
+		self::_errorLog(date("Y-m-d H:i:s : ")
904
+						.basename($_SERVER['PHP_SELF'])
905
+						.sprintf(_("release job %s: OPERATION FAILED"),
906
+									 $job_uri),3);
907
+
908
+		return false;
909
+	}
910
+
911
+
912
+	public function restartJob ($job_uri)
913
+	{
914
+		$this->jobs = array_merge($this->jobs,array(""));
915
+		$this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
916
+
917
+		self::_setOperationId();
918
+		$this->parsed = array();
919
+		unset($this->printer_attributes);
920
+
921
+		if (!isset($this->setup->charset))
922
+		{
923
+			self::setCharset();
924
+		}
925
+
926
+		if (!isset($this->setup->language))
927
+		{
928
+			self::setLanguage('en_us');
929
+		}
930
+
931
+		if (!isset($this->meta->username))
932
+		{
933
+			self::setUserName();
934
+		}
935
+
936
+		if (!isset($this->meta->message))
937
+		{
938
+			$this->meta->message = '';
939
+		}
940
+
941
+		self::_setJobUri($job_uri);
942
+
943
+		$jobattributes = '';
944
+		$operationattributes = '';
945
+		$printerattributes = '';
946
+		self::_buildValues ($operationattributes,$jobattributes,$printerattributes); 
947 947
  
948
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
949
-                         . chr(0x00) . chr (0x0E) // Hold-Job | operation-id
950
-                         . $this->meta->operation_id //           request-id
951
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
952
-                         . $this->meta->charset
953
-                         . $this->meta->language
954
-                         . $this->meta->job_uri
955
-                         . $this->meta->username
956
-                         . $this->meta->message
957
-                         . $jobattributes // job-hold-until is set by setAttribute($attribute,$value)
958
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
959
-
960
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
961
-
962
-        self::_putDebug(sprintf(_("release job %s\n"),$job_uri)); 
963
-
964
-        $this->output = $this->stringjob;
965
-
966
-        $post_values = array( "Content-Type"=>"application/ipp",
967
-                              "Data"=>$this->output);
968
-
969
-        if (self::_sendHttp ($post_values,$this->paths['jobs']))
970
-        {
971
-            self::_parseServerOutput();
972
-            self::_parseAttributes();
973
-        }
974
-
975
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
976
-        {
977
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
978
-
979
-            if ($this->serveroutput->status == "successfull-ok")
980
-            {
981
-                self::_errorLog(sprintf(_("release job %s: "),$job_uri)
982
-                            .$this->serveroutput->status,3);
983
-            }
984
-            else
985
-            {
986
-                 self::_errorLog(sprintf(_("release job %s: "),$job_uri)
987
-                                             .$this->serveroutput->status,1);
988
-            }
989
-
990
-            return $this->serveroutput->status; 
991
-        }
992
-
993
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
994
-        self::_errorLog(date("Y-m-d H:i:s : ")
995
-                        .basename($_SERVER['PHP_SELF'])
996
-                        .sprintf(_("release job %s: OPERATION FAILED"),
997
-                                     $job_uri),3);
998
-
999
-        return false;
1000
-    }
1001
-
1002
-
1003
-    public function setJobAttributes ($job_uri,$deleted_attributes=array())
1004
-    {
1005
-        $this->jobs = array_merge($this->jobs,array(""));
1006
-        $this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
1007
-
1008
-        self::_setOperationId();
1009
-        $this->parsed = array();
1010
-        unset ($this->attributes);
1011
-
1012
-        if (!isset($this->setup->charset))
1013
-        {
1014
-            self::setCharset();
1015
-        }
1016
-
1017
-        if (!isset($this->setup->language))
1018
-        {
1019
-            self::setLanguage('en_us');
1020
-        }
1021
-
1022
-        if (!isset($this->meta->username))
1023
-        {
1024
-            self::setUserName();
1025
-        }
1026
-
1027
-        if (!isset($this->meta->message))
1028
-        {
1029
-            $this->meta->message = '';
1030
-        }
1031
-
1032
-        if (!isset($this->meta->copies))
1033
-        {
1034
-            $this->meta->copies = '';
1035
-        }
1036
-
1037
-        if (!isset($this->meta->sides))
1038
-        {
1039
-            $this->meta->sides = '';
1040
-        }
1041
-
1042
-        if (!isset($this->meta->page_ranges))
1043
-        {
1044
-            $this->meta->page_ranges = '';
1045
-        }
948
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
949
+						 . chr(0x00) . chr (0x0E) // Hold-Job | operation-id
950
+						 . $this->meta->operation_id //           request-id
951
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
952
+						 . $this->meta->charset
953
+						 . $this->meta->language
954
+						 . $this->meta->job_uri
955
+						 . $this->meta->username
956
+						 . $this->meta->message
957
+						 . $jobattributes // job-hold-until is set by setAttribute($attribute,$value)
958
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
959
+
960
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
961
+
962
+		self::_putDebug(sprintf(_("release job %s\n"),$job_uri)); 
963
+
964
+		$this->output = $this->stringjob;
965
+
966
+		$post_values = array( "Content-Type"=>"application/ipp",
967
+							  "Data"=>$this->output);
968
+
969
+		if (self::_sendHttp ($post_values,$this->paths['jobs']))
970
+		{
971
+			self::_parseServerOutput();
972
+			self::_parseAttributes();
973
+		}
974
+
975
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
976
+		{
977
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
978
+
979
+			if ($this->serveroutput->status == "successfull-ok")
980
+			{
981
+				self::_errorLog(sprintf(_("release job %s: "),$job_uri)
982
+							.$this->serveroutput->status,3);
983
+			}
984
+			else
985
+			{
986
+				 self::_errorLog(sprintf(_("release job %s: "),$job_uri)
987
+											 .$this->serveroutput->status,1);
988
+			}
989
+
990
+			return $this->serveroutput->status; 
991
+		}
992
+
993
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
994
+		self::_errorLog(date("Y-m-d H:i:s : ")
995
+						.basename($_SERVER['PHP_SELF'])
996
+						.sprintf(_("release job %s: OPERATION FAILED"),
997
+									 $job_uri),3);
998
+
999
+		return false;
1000
+	}
1001
+
1002
+
1003
+	public function setJobAttributes ($job_uri,$deleted_attributes=array())
1004
+	{
1005
+		$this->jobs = array_merge($this->jobs,array(""));
1006
+		$this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
1007
+
1008
+		self::_setOperationId();
1009
+		$this->parsed = array();
1010
+		unset ($this->attributes);
1011
+
1012
+		if (!isset($this->setup->charset))
1013
+		{
1014
+			self::setCharset();
1015
+		}
1016
+
1017
+		if (!isset($this->setup->language))
1018
+		{
1019
+			self::setLanguage('en_us');
1020
+		}
1021
+
1022
+		if (!isset($this->meta->username))
1023
+		{
1024
+			self::setUserName();
1025
+		}
1026
+
1027
+		if (!isset($this->meta->message))
1028
+		{
1029
+			$this->meta->message = '';
1030
+		}
1031
+
1032
+		if (!isset($this->meta->copies))
1033
+		{
1034
+			$this->meta->copies = '';
1035
+		}
1036
+
1037
+		if (!isset($this->meta->sides))
1038
+		{
1039
+			$this->meta->sides = '';
1040
+		}
1041
+
1042
+		if (!isset($this->meta->page_ranges))
1043
+		{
1044
+			$this->meta->page_ranges = '';
1045
+		}
1046 1046
   
1047
-        self::_setJobUri($job_uri);
1048
-
1049
-        $operationattributes = '';
1050
-        $jobattributes = '';
1051
-        $printerattributes = '';
1052
-        self::_buildValues ($operationattributes,$jobattributes,$printerattributes); 
1053
-
1054
-        $this->meta->deleted_attributes = "";
1055
-        for ($i = 0 ; $i < count($deleted_attributes) ; $i++)
1056
-        {
1057
-            $this->meta->deleted_attributes .= chr(0x16) // out-of-band value
1058
-                . self::_giveMeStringLength($deleted_attributes[$i])
1059
-                . $deleted_attributes[$i]
1060
-                . chr(0x0).chr(0x0);
1061
-        } // value-length = 0;
1062
-
1063
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1064
-                         . chr(0x00) . chr (0x14) // Set-Job-Attributes | operation-id
1065
-                         . $this->meta->operation_id //           request-id
1066
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
1067
-                         . $this->meta->charset
1068
-                         . $this->meta->language
1069
-                         . $this->meta->job_uri
1070
-                         . $this->meta->username
1071
-                         . $this->meta->message
1072
-                         . chr(0x02) // start job-attributes
1073
-                         . $jobattributes // setteds by setAttribute($attribute,$value)
1074
-                         . $this->meta->copies
1075
-                         . $this->meta->sides
1076
-                         . $this->meta->page_ranges
1077
-                         . $this->meta->deleted_attributes
1078
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
1079
-
1080
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1081
-
1082
-        self::_putDebug(sprintf(_("set job attributes for job %s\n"),$job_uri)); 
1083
-
1084
-        $this->output = $this->stringjob;
1085
-
1086
-        $post_values = array( "Content-Type"=>"application/ipp",
1087
-                              "Data"=>$this->output);
1088
-
1089
-        if (self::_sendHttp ($post_values,$this->paths['jobs']))
1090
-        {
1091
-            self::_parseServerOutput();
1092
-            self::_parseAttributes();
1093
-        }
1094
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
1095
-        {
1096
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
1097
-
1098
-            if ($this->serveroutput->status == "successfull-ok")
1099
-            {
1100
-                self::_errorLog(sprintf(_("set job attributes for job %s: "),$job_uri)
1101
-                            .$this->serveroutput->status,3);
1102
-            }
1103
-            else
1104
-            {
1105
-                 self::_errorLog(sprintf(_("set job attributes for job %s: "),$job_uri)
1106
-                                             .$this->serveroutput->status,1);
1107
-            }
1108
-            $this->last_job = $job_uri;
1109
-            $this->jobs_uri[count($this->jobs_uri) - 1] = $job_uri;
1110
-            return $this->serveroutput->status; 
1111
-        }
1112
-
1113
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
1114
-        self::_errorLog(date("Y-m-d H:i:s : ")
1115
-                        .basename($_SERVER['PHP_SELF'])
1116
-                        .sprintf(_("set job attributes for job %s: OPERATION FAILED"),
1117
-                                     $job_uri),3);
1118
-
1119
-        return false;
1120
-    }
1121
-
1122
-
1123
-    public function setPrinterAttributes ($document_format='',$deleted_attributes=array())
1124
-    {
1125
-        /* $document_format (RFC 3380)
1047
+		self::_setJobUri($job_uri);
1048
+
1049
+		$operationattributes = '';
1050
+		$jobattributes = '';
1051
+		$printerattributes = '';
1052
+		self::_buildValues ($operationattributes,$jobattributes,$printerattributes); 
1053
+
1054
+		$this->meta->deleted_attributes = "";
1055
+		for ($i = 0 ; $i < count($deleted_attributes) ; $i++)
1056
+		{
1057
+			$this->meta->deleted_attributes .= chr(0x16) // out-of-band value
1058
+				. self::_giveMeStringLength($deleted_attributes[$i])
1059
+				. $deleted_attributes[$i]
1060
+				. chr(0x0).chr(0x0);
1061
+		} // value-length = 0;
1062
+
1063
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1064
+						 . chr(0x00) . chr (0x14) // Set-Job-Attributes | operation-id
1065
+						 . $this->meta->operation_id //           request-id
1066
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
1067
+						 . $this->meta->charset
1068
+						 . $this->meta->language
1069
+						 . $this->meta->job_uri
1070
+						 . $this->meta->username
1071
+						 . $this->meta->message
1072
+						 . chr(0x02) // start job-attributes
1073
+						 . $jobattributes // setteds by setAttribute($attribute,$value)
1074
+						 . $this->meta->copies
1075
+						 . $this->meta->sides
1076
+						 . $this->meta->page_ranges
1077
+						 . $this->meta->deleted_attributes
1078
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
1079
+
1080
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1081
+
1082
+		self::_putDebug(sprintf(_("set job attributes for job %s\n"),$job_uri)); 
1083
+
1084
+		$this->output = $this->stringjob;
1085
+
1086
+		$post_values = array( "Content-Type"=>"application/ipp",
1087
+							  "Data"=>$this->output);
1088
+
1089
+		if (self::_sendHttp ($post_values,$this->paths['jobs']))
1090
+		{
1091
+			self::_parseServerOutput();
1092
+			self::_parseAttributes();
1093
+		}
1094
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
1095
+		{
1096
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
1097
+
1098
+			if ($this->serveroutput->status == "successfull-ok")
1099
+			{
1100
+				self::_errorLog(sprintf(_("set job attributes for job %s: "),$job_uri)
1101
+							.$this->serveroutput->status,3);
1102
+			}
1103
+			else
1104
+			{
1105
+				 self::_errorLog(sprintf(_("set job attributes for job %s: "),$job_uri)
1106
+											 .$this->serveroutput->status,1);
1107
+			}
1108
+			$this->last_job = $job_uri;
1109
+			$this->jobs_uri[count($this->jobs_uri) - 1] = $job_uri;
1110
+			return $this->serveroutput->status; 
1111
+		}
1112
+
1113
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
1114
+		self::_errorLog(date("Y-m-d H:i:s : ")
1115
+						.basename($_SERVER['PHP_SELF'])
1116
+						.sprintf(_("set job attributes for job %s: OPERATION FAILED"),
1117
+									 $job_uri),3);
1118
+
1119
+		return false;
1120
+	}
1121
+
1122
+
1123
+	public function setPrinterAttributes ($document_format='',$deleted_attributes=array())
1124
+	{
1125
+		/* $document_format (RFC 3380)
1126 1126
          If the client includes this attribute, the Printer MUST change
1127 1127
          the supplied attributes for the document format specified by
1128 1128
          this attribute.  If a supplied attribute is a member of the
@@ -1140,517 +1140,517 @@  discard block
 block discarded – undo
1140 1140
          they vary by document-format.
1141 1141
          */
1142 1142
 
1143
-        $this->jobs = array_merge($this->jobs,array(""));
1144
-        $this->jobs_uri = array_merge($this->jobs_uri,array(""));
1145
-        unset ($this->attributes);
1146
-
1147
-        self::_setOperationId();
1148
-        $this->parsed = array();
1149
-
1150
-        if (!isset($this->setup->charset))
1151
-        {
1152
-            self::setCharset();
1153
-        }
1154
-
1155
-        if (!isset($this->setup->language))
1156
-        {
1157
-            self::setLanguage('en_us');
1158
-        }
1159
-
1160
-        if (!isset($this->meta->username))
1161
-        {
1162
-            self::setUserName();
1163
-        }
1164
-
1165
-        if (!isset($this->meta->message))
1166
-        {
1167
-            $this->meta->message = '';
1168
-        }
1169
-
1170
-        if (!isset($this->meta->copies))
1171
-        {
1172
-            $this->meta->copies = '';
1173
-        }
1174
-
1175
-        if (!isset($this->meta->sides))
1176
-        {
1177
-            $this->meta->sides = '';
1178
-        }
1179
-
1180
-        if (!isset($this->meta->page_ranges))
1181
-        {
1182
-            $this->meta->page_ranges = '';
1183
-        }
1184
-
1185
-        if ($document_format)
1186
-        {
1187
-        $document_format = chr(0x49) // document-format tag
1188
-            . self::_giveMeStringLength('document-format')
1189
-            . 'document-format' // 
1190
-            . self::_giveMeStringLength($document_format)
1191
-            . $document_format;
1192
-        } // value
1193
-
1194
-        $operationattributes = '';
1195
-        $jobattributes = '';
1196
-        $printerattributes = '';
1197
-        self::_buildValues ($operationattributes,$jobattributes,$printerattributes); 
1198
-
1199
-        $this->meta->deleted_attributes = "";
1200
-        for ($i = 0 ; $i < count($deleted_attributes) ; $i++)
1201
-        {
1202
-                $this->meta->deleted_attributes .= chr(0x16) // out-of-band "deleted" value
1203
-                                                . self::_giveMeStringLength($deleted_attributes[$i])
1204
-                                                . $deleted_attributes[$i]
1205
-                                                . chr(0x0).chr(0x0);
1206
-        } // value-length = 0;
1207
-
1208
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1209
-                         . chr(0x00) . chr (0x13) // Set-Printer-Attributes | operation-id
1210
-                         . $this->meta->operation_id //           request-id
1211
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
1212
-                         . $this->meta->charset
1213
-                         . $this->meta->language
1214
-                         . $this->meta->printer_uri
1215
-                         . $this->meta->username
1216
-                         . $this->meta->message
1217
-                         . $operationattributes
1218
-                         . chr(0x02) // start job-attributes
1219
-                         . $jobattributes // setteds by setAttribute($attribute,$value)
1220
-                         . $this->meta->copies
1221
-                         . $this->meta->sides
1222
-                         . $this->meta->page_ranges
1223
-                         . $this->meta->deleted_attributes
1224
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
1225
-
1226
-        self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1227
-
1228
-        self::_putDebug(sprintf(_("set printer attributes for job %s\n"),$this->printer_uri)); 
1229
-
1230
-        $this->output = $this->stringjob;
1231
-
1232
-        $post_values = array( "Content-Type"=>"application/ipp",
1233
-                              "Data"=>$this->output);
1234
-
1235
-        if (self::_sendHttp ($post_values,$this->paths['printers']))
1236
-        {
1237
-            self::_parseServerOutput();
1238
-            self::_parseAttributes();
1239
-        }
1240
-        if (isset($this->serveroutput) && isset($this->serveroutput->status))
1241
-        {
1242
-            $this->status = array_merge($this->status,array($this->serveroutput->status));
1243
-
1244
-            if ($this->serveroutput->status == "successfull-ok")
1245
-            {
1246
-                self::_errorLog(sprintf(_("set printer attributes for printer %s: "),$this->printer_uri)
1247
-                            .$this->serveroutput->status,3);
1248
-            }
1249
-            else
1250
-            {
1251
-                 self::_errorLog(sprintf(_("set printer attributes for printer %s: "),$this->printer_uri)
1252
-                                             .$this->serveroutput->status,1);
1253
-            }
1254
-
1255
-            return $this->serveroutput->status; 
1256
-        }
1257
-
1258
-        $this->status = array_merge($this->status,array("OPERATION FAILED"));
1259
-        self::_errorLog(date("Y-m-d H:i:s : ")
1260
-                        .basename($_SERVER['PHP_SELF'])
1261
-                        .sprintf(_("set printer attributes for printer %s: OPERATION FAILED"),
1262
-                                     $this->printer_uri),1);
1263
-
1264
-        return false;
1265
-    }
1266
-
1267
-    // REQUEST BUILDING
1268
-    protected function _setDocumentUri ()
1269
-    {
1270
-        $this->meta->document_uri = chr(0x45) // type uri
1271
-                                . chr(0x00).chr(0x0c) // name-length
1272
-                                . "document-uri"
1273
-                                . self::_giveMeStringLength($this->document_uri)
1274
-                                . $this->document_uri;
1275
-
1276
-        self::_putDebug( "document uri is: ".$this->document_uri."\n");
1277
-        $this->setup->document_uri = 1;
1278
-    }
1279
-
1280
-
1281
-    protected function _stringUri ()
1282
-    {
1283
-        self::_setDocumentUri();
1284
-
1285
-        if (!isset($this->setup->document_uri))
1286
-        {
1287
-            trigger_error(_("_stringUri: Document URI is not set: die"),E_USER_WARNING);
1288
-            self::_putDebug( _("_stringUri: Document URI is not set: die\n"));
1289
-            self::_errorLog("Document URI is not set, die",2);
1290
-            return FALSE;
1291
-        }
1292
-        unset ($this->setup->document_uri);
1293
-
1294
-        if (!isset($this->setup->uri))
1295
-        {
1296
-            $this->getPrinters();
1297
-            unset($this->jobs[count($this->jobs) - 1]);
1298
-            unset($this->jobs_uri[count($this->jobs) - 1]);
1299
-            unset($this->status[count($this->status) - 1]);
1300
-
1301
-            if (array_key_exists(0,$this->available_printers))
1302
-            {
1303
-               self::setPrinterURI($this->available_printers[0]);
1304
-            }
1305
-            else
1306
-            {
1307
-                trigger_error(_("_stringUri: Printer URI is not set: die"),E_USER_WARNING);
1308
-                self::_putDebug( _("_stringUri: Printer URI is not set: die\n"));
1309
-                self::_errorLog("_stringUri: Printer URI is not set, die",2);
1310
-                return FALSE;
1311
-            }
1312
-        }
1143
+		$this->jobs = array_merge($this->jobs,array(""));
1144
+		$this->jobs_uri = array_merge($this->jobs_uri,array(""));
1145
+		unset ($this->attributes);
1146
+
1147
+		self::_setOperationId();
1148
+		$this->parsed = array();
1149
+
1150
+		if (!isset($this->setup->charset))
1151
+		{
1152
+			self::setCharset();
1153
+		}
1154
+
1155
+		if (!isset($this->setup->language))
1156
+		{
1157
+			self::setLanguage('en_us');
1158
+		}
1159
+
1160
+		if (!isset($this->meta->username))
1161
+		{
1162
+			self::setUserName();
1163
+		}
1164
+
1165
+		if (!isset($this->meta->message))
1166
+		{
1167
+			$this->meta->message = '';
1168
+		}
1169
+
1170
+		if (!isset($this->meta->copies))
1171
+		{
1172
+			$this->meta->copies = '';
1173
+		}
1174
+
1175
+		if (!isset($this->meta->sides))
1176
+		{
1177
+			$this->meta->sides = '';
1178
+		}
1179
+
1180
+		if (!isset($this->meta->page_ranges))
1181
+		{
1182
+			$this->meta->page_ranges = '';
1183
+		}
1184
+
1185
+		if ($document_format)
1186
+		{
1187
+		$document_format = chr(0x49) // document-format tag
1188
+			. self::_giveMeStringLength('document-format')
1189
+			. 'document-format' // 
1190
+			. self::_giveMeStringLength($document_format)
1191
+			. $document_format;
1192
+		} // value
1193
+
1194
+		$operationattributes = '';
1195
+		$jobattributes = '';
1196
+		$printerattributes = '';
1197
+		self::_buildValues ($operationattributes,$jobattributes,$printerattributes); 
1198
+
1199
+		$this->meta->deleted_attributes = "";
1200
+		for ($i = 0 ; $i < count($deleted_attributes) ; $i++)
1201
+		{
1202
+				$this->meta->deleted_attributes .= chr(0x16) // out-of-band "deleted" value
1203
+												. self::_giveMeStringLength($deleted_attributes[$i])
1204
+												. $deleted_attributes[$i]
1205
+												. chr(0x0).chr(0x0);
1206
+		} // value-length = 0;
1207
+
1208
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1209
+						 . chr(0x00) . chr (0x13) // Set-Printer-Attributes | operation-id
1210
+						 . $this->meta->operation_id //           request-id
1211
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
1212
+						 . $this->meta->charset
1213
+						 . $this->meta->language
1214
+						 . $this->meta->printer_uri
1215
+						 . $this->meta->username
1216
+						 . $this->meta->message
1217
+						 . $operationattributes
1218
+						 . chr(0x02) // start job-attributes
1219
+						 . $jobattributes // setteds by setAttribute($attribute,$value)
1220
+						 . $this->meta->copies
1221
+						 . $this->meta->sides
1222
+						 . $this->meta->page_ranges
1223
+						 . $this->meta->deleted_attributes
1224
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
1225
+
1226
+		self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1227
+
1228
+		self::_putDebug(sprintf(_("set printer attributes for job %s\n"),$this->printer_uri)); 
1229
+
1230
+		$this->output = $this->stringjob;
1231
+
1232
+		$post_values = array( "Content-Type"=>"application/ipp",
1233
+							  "Data"=>$this->output);
1234
+
1235
+		if (self::_sendHttp ($post_values,$this->paths['printers']))
1236
+		{
1237
+			self::_parseServerOutput();
1238
+			self::_parseAttributes();
1239
+		}
1240
+		if (isset($this->serveroutput) && isset($this->serveroutput->status))
1241
+		{
1242
+			$this->status = array_merge($this->status,array($this->serveroutput->status));
1243
+
1244
+			if ($this->serveroutput->status == "successfull-ok")
1245
+			{
1246
+				self::_errorLog(sprintf(_("set printer attributes for printer %s: "),$this->printer_uri)
1247
+							.$this->serveroutput->status,3);
1248
+			}
1249
+			else
1250
+			{
1251
+				 self::_errorLog(sprintf(_("set printer attributes for printer %s: "),$this->printer_uri)
1252
+											 .$this->serveroutput->status,1);
1253
+			}
1254
+
1255
+			return $this->serveroutput->status; 
1256
+		}
1257
+
1258
+		$this->status = array_merge($this->status,array("OPERATION FAILED"));
1259
+		self::_errorLog(date("Y-m-d H:i:s : ")
1260
+						.basename($_SERVER['PHP_SELF'])
1261
+						.sprintf(_("set printer attributes for printer %s: OPERATION FAILED"),
1262
+									 $this->printer_uri),1);
1263
+
1264
+		return false;
1265
+	}
1266
+
1267
+	// REQUEST BUILDING
1268
+	protected function _setDocumentUri ()
1269
+	{
1270
+		$this->meta->document_uri = chr(0x45) // type uri
1271
+								. chr(0x00).chr(0x0c) // name-length
1272
+								. "document-uri"
1273
+								. self::_giveMeStringLength($this->document_uri)
1274
+								. $this->document_uri;
1275
+
1276
+		self::_putDebug( "document uri is: ".$this->document_uri."\n");
1277
+		$this->setup->document_uri = 1;
1278
+	}
1279
+
1280
+
1281
+	protected function _stringUri ()
1282
+	{
1283
+		self::_setDocumentUri();
1284
+
1285
+		if (!isset($this->setup->document_uri))
1286
+		{
1287
+			trigger_error(_("_stringUri: Document URI is not set: die"),E_USER_WARNING);
1288
+			self::_putDebug( _("_stringUri: Document URI is not set: die\n"));
1289
+			self::_errorLog("Document URI is not set, die",2);
1290
+			return FALSE;
1291
+		}
1292
+		unset ($this->setup->document_uri);
1293
+
1294
+		if (!isset($this->setup->uri))
1295
+		{
1296
+			$this->getPrinters();
1297
+			unset($this->jobs[count($this->jobs) - 1]);
1298
+			unset($this->jobs_uri[count($this->jobs) - 1]);
1299
+			unset($this->status[count($this->status) - 1]);
1300
+
1301
+			if (array_key_exists(0,$this->available_printers))
1302
+			{
1303
+			   self::setPrinterURI($this->available_printers[0]);
1304
+			}
1305
+			else
1306
+			{
1307
+				trigger_error(_("_stringUri: Printer URI is not set: die"),E_USER_WARNING);
1308
+				self::_putDebug( _("_stringUri: Printer URI is not set: die\n"));
1309
+				self::_errorLog("_stringUri: Printer URI is not set, die",2);
1310
+				return FALSE;
1311
+			}
1312
+		}
1313 1313
   
1314
-        if (!isset($this->setup->charset))
1315
-        {
1316
-            $this->meta->charset = "";
1317
-        }
1318
-        if (!isset($this->setup->datatype))
1319
-        {
1320
-            self::setBinary();
1321
-        }
1322
-        if (!isset($this->setup->uri))
1323
-        {
1324
-            trigger_error(_("_stringUri: Printer URI is not set: die"),E_USER_WARNING);
1325
-            self::_putDebug( _("_stringUri: Printer URI is not set: die\n"));
1326
-            self::_errorLog("Printer URI is not set, die",2);
1327
-            return FALSE;
1328
-        }
1329
-        if (!isset($this->setup->copies))
1330
-        {
1331
-            self::setCopies(1);
1332
-        }
1333
-
1334
-        if (!isset($this->setup->language))
1335
-        {
1336
-            self::setLanguage('en_us');
1337
-        }
1338
-
1339
-        if (!isset($this->setup->mime_media_type))
1340
-        {
1341
-            self::setMimeMediaType();
1342
-        }
1343
-        unset ($this->setup->mime_media_type);
1344
-
1345
-        if (!isset($this->setup->jobname))
1346
-        {
1347
-            if (is_readable($this->data))
1348
-            {
1349
-                self::setJobName(basename($this->data),true);
1350
-            }
1351
-            else
1352
-            {
1353
-                self::setJobName();
1354
-            }
1355
-        }
1356
-        unset($this->setup->jobname);
1357
-
1358
-        if (!isset($this->meta->username))
1359
-        {
1360
-            self::setUserName();
1361
-        }
1362
-
1363
-        if (!isset($this->meta->fidelity))
1364
-        {
1365
-            $this->meta->fidelity = '';
1366
-        }
1367
-
1368
-        if (!isset($this->meta->document_name))
1369
-        {
1370
-            $this->meta->document_name = '';
1371
-        }
1372
-
1373
-        if (!isset($this->meta->sides))
1374
-        {
1375
-            $this->meta->sides = '';
1376
-        }
1377
-
1378
-        if (!isset($this->meta->page_ranges))
1379
-        {
1380
-            $this->meta->page_ranges = '';
1381
-        }
1382
-
1383
-        $jobattributes = '';
1384
-        $operationattributes = '';
1385
-        $printerattributes = '';
1386
-        self::_buildValues($operationattributes,$jobattributes,$printerattributes);
1387
-
1388
-        self::_setOperationId();
1389
-
1390
-        if (!isset($this->error_generation->request_body_malformed))
1391
-        {
1392
-            $this->error_generation->request_body_malformed = "";
1393
-        }
1394
-
1395
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1396
-                         . chr(0x00) . chr (0x03) // Print-URI | operation-id
1397
-                         . $this->meta->operation_id //           request-id
1398
-                         . $this->error_generation->request_body_malformed
1399
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
1400
-                         . $this->meta->charset
1401
-                         . $this->meta->language
1402
-                         . $this->meta->printer_uri
1403
-                         . $this->meta->jobname
1404
-                         . $this->meta->username
1405
-                         . $this->meta->fidelity
1406
-                         . $this->meta->document_name
1407
-                         . $this->meta->document_uri
1408
-                         . $operationattributes
1409
-                         . chr(0x02) // start job-attributes | job-attributes-tag
1410
-                         . $this->meta->copies
1411
-                         . $this->meta->sides
1412
-                         . $this->meta->page_ranges
1413
-                         . $jobattributes
1414
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
1415
-
1416
-        self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1417
-        return TRUE;
1418
-    }
1419
-
1420
-
1421
-    protected function _stringDocument ($job,$is_last)
1422
-    {
1423
-        if ($is_last == false)
1424
-        {
1425
-            $is_last = chr(0x00);
1426
-        }
1427
-        else
1428
-        {
1429
-            $is_last = chr(0x01);
1430
-        }
1431
-
1432
-        if (!isset($this->setup->charset))
1433
-        {
1434
-            self::setCharset();
1435
-        }
1436
-        if (!isset($this->setup->datatype))
1437
-        {
1438
-            self::setBinary();
1439
-        }
1440
-
1441
-        if (!isset($this->setup->uri))
1442
-        {
1443
-            $this->getPrinters();
1444
-            unset($this->jobs[count($this->jobs) - 1]);
1445
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
1446
-            unset($this->status[count($this->status) - 1]);
1447
-
1448
-            if (array_key_exists(0,$this->available_printers))
1449
-            {
1450
-               self::setPrinterURI($this->available_printers[0]);
1451
-            }
1452
-            else
1453
-            {
1454
-                trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
1455
-                self::_putDebug( _("_stringJob: Printer URI is not set: die\n"));
1456
-                self::_errorLog(" Printer URI is not set, die",2);
1457
-                return FALSE;
1458
-                }
1459
-            }
1460
-
1461
-        if (!isset($this->setup->copies))
1462
-        {
1463
-            $this->meta->copies = "";
1464
-        }
1465
-
1466
-        if (!isset($this->setup->language))
1467
-        {
1468
-            self::setLanguage('en_us');
1469
-        }
1470
-
1471
-        if (!isset($this->setup->mime_media_type))
1472
-        {
1473
-            $this->meta->mime_media_type = "";
1474
-        }
1475
-        if ($this->setup->datatype != "TEXT")
1476
-        {
1477
-        unset ($this->setup->mime_media_type);
1478
-        }
1479
-
1480
-        if (!isset($this->meta->fidelity))
1481
-        {
1482
-            $this->meta->fidelity = '';
1483
-        }
1484
-
1485
-        if (!isset($this->meta->document_name))
1486
-        {
1487
-            $this->meta->document_name = '';
1488
-        }
1489
-
1490
-        if (!isset($this->meta->sides))
1491
-        {
1492
-            $this->meta->sides = '';
1493
-        }
1494
-
1495
-        if (!isset($this->meta->page_ranges))
1496
-        {
1497
-            $this->meta->page_ranges = '';
1498
-        }
1499
-
1500
-        $operationattributes = '';
1501
-        $jobattributes = '';
1502
-        $printerattributes = '';
1503
-        self::_buildValues($operationattributes,$jobattributes,$printerattributes);
1504
-
1505
-        self::_setOperationId();
1506
-
1507
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1508
-                         . chr(0x00) . chr (0x06) // Send-Document | operation-id
1509
-                         . $this->meta->operation_id //           request-id
1510
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
1511
-                         . $this->meta->charset
1512
-                         . $this->meta->language
1513
-                         . chr(0x45) // attribute-type: uri
1514
-                         . self::_giveMeStringLength("job-uri")
1515
-                         . "job-uri"
1516
-                         . self::_giveMeStringLength($job)
1517
-                         . $job
1518
-                         . $this->meta->username
1519
-                         . $this->meta->document_name
1520
-                         . $this->meta->fidelity
1521
-                         . $this->meta->mime_media_type
1522
-                         . $operationattributes
1523
-                         . chr(0x22) // boolean
1524
-                         . self::_giveMeStringLength("last-document")
1525
-                         . "last-document"
1526
-                         . self::_giveMeStringLength($is_last)
1527
-                         . $is_last
1528
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
1529
-
1530
-        self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1531
-        return TRUE;
1532
-    }
1533
-
1534
-
1535
-    protected function _stringSendUri ($uri,$job,$is_last)
1536
-    {
1537
-        $this->document_uri = $uri;
1538
-        self::_setDocumentUri();
1539
-
1540
-        if (!isset($this->setup->document_uri))
1541
-        {
1542
-            trigger_error(_("_stringUri: Document URI is not set: die"),E_USER_WARNING);
1543
-            self::_putDebug( _("_stringUri: Document URI is not set: die\n"));
1544
-            self::_errorLog("Document URI is not set, die",2);
1545
-            return FALSE;
1546
-        }
1547
-        unset ($this->setup->document_uri);
1548
-
1549
-        if ($is_last == false)
1550
-        {
1551
-            $is_last = chr(0x00);
1552
-        }
1553
-        else
1554
-        {
1555
-            $is_last = chr(0x01);
1556
-        }
1557
-
1558
-        if (!isset($this->setup->charset))
1559
-        {
1560
-            self::setCharset();
1561
-        }
1562
-        if (!isset($this->setup->datatype))
1563
-        {
1564
-            self::setBinary();
1565
-        }
1566
-
1567
-        if (!isset($this->setup->uri))
1568
-        {
1569
-            $this->getPrinters();
1570
-            unset($this->jobs[count($this->jobs) - 1]);
1571
-            unset($this->jobs_uri[count($this->jobs_uri) - 1]);
1572
-            unset($this->status[count($this->status) - 1]);
1573
-
1574
-            if (array_key_exists(0,$this->available_printers))
1575
-            {
1576
-               self::setPrinterURI($this->available_printers[0]);
1577
-            } 
1578
-            else
1579
-            {
1580
-                trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
1581
-                self::_putDebug( _("_stringJob: Printer URI is not set: die\n"));
1582
-                self::_errorLog(" Printer URI is not set, die",2);
1583
-                return FALSE;
1584
-                }
1585
-            }
1586
-
1587
-        if (!isset($this->setup->copies))
1588
-        {
1589
-            $this->meta->copies = "";
1590
-        }
1591
-
1592
-        if (!isset($this->setup->language))
1593
-        {
1594
-            self::setLanguage('en_us');
1595
-        }
1596
-
1597
-        if (!isset($this->setup->mime_media_type))
1598
-        {
1599
-            $this->meta->mime_media_type = "";
1600
-        }
1601
-        unset ($this->setup->mime_media_type);
1602
-
1603
-        if (!isset($this->meta->fidelity))
1604
-        {
1605
-            $this->meta->fidelity = '';
1606
-        }
1607
-
1608
-        if (!isset($this->meta->document_name))
1609
-        {
1610
-            $this->meta->document_name = '';
1611
-        }
1612
-
1613
-        if (!isset($this->meta->sides))
1614
-        {
1615
-            $this->meta->sides = '';
1616
-        }
1617
-
1618
-        if (!isset($this->meta->page_ranges))
1619
-        {
1620
-            $this->meta->page_ranges = '';
1621
-        }
1622
-
1623
-        $operationattributes = '';
1624
-        $jobattributes = '';
1625
-        $printerattributes = '';
1626
-        self::_buildValues($operationattributes,$jobattributes,$printerattributes);
1627
-
1628
-        self::_setOperationId();
1629
-
1630
-        $this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1631
-                         . chr(0x00) . chr (0x07) // Send-Uri | operation-id
1632
-                         . $this->meta->operation_id //           request-id
1633
-                         . chr(0x01) // start operation-attributes | operation-attributes-tag
1634
-                         . $this->meta->charset
1635
-                         . $this->meta->language
1636
-                         . chr(0x45) // attribute-type: uri
1637
-                         . self::_giveMeStringLength("job-uri")
1638
-                         . "job-uri"
1639
-                         . self::_giveMeStringLength($job)
1640
-                         . $job
1641
-                         . $this->meta->username
1642
-                         . $this->meta->document_uri
1643
-                         . $this->meta->fidelity
1644
-                         . $this->meta->mime_media_type
1645
-                         . $operationattributes
1646
-                         . chr(0x22) // boolean
1647
-                         . self::_giveMeStringLength("last-document")
1648
-                         . "last-document"
1649
-                         . self::_giveMeStringLength($is_last)
1650
-                         . $is_last
1651
-                         . chr(0x03); // end-of-attributes | end-of-attributes-tag
1652
-
1653
-        self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1654
-        return TRUE;
1655
-    }
1314
+		if (!isset($this->setup->charset))
1315
+		{
1316
+			$this->meta->charset = "";
1317
+		}
1318
+		if (!isset($this->setup->datatype))
1319
+		{
1320
+			self::setBinary();
1321
+		}
1322
+		if (!isset($this->setup->uri))
1323
+		{
1324
+			trigger_error(_("_stringUri: Printer URI is not set: die"),E_USER_WARNING);
1325
+			self::_putDebug( _("_stringUri: Printer URI is not set: die\n"));
1326
+			self::_errorLog("Printer URI is not set, die",2);
1327
+			return FALSE;
1328
+		}
1329
+		if (!isset($this->setup->copies))
1330
+		{
1331
+			self::setCopies(1);
1332
+		}
1333
+
1334
+		if (!isset($this->setup->language))
1335
+		{
1336
+			self::setLanguage('en_us');
1337
+		}
1338
+
1339
+		if (!isset($this->setup->mime_media_type))
1340
+		{
1341
+			self::setMimeMediaType();
1342
+		}
1343
+		unset ($this->setup->mime_media_type);
1344
+
1345
+		if (!isset($this->setup->jobname))
1346
+		{
1347
+			if (is_readable($this->data))
1348
+			{
1349
+				self::setJobName(basename($this->data),true);
1350
+			}
1351
+			else
1352
+			{
1353
+				self::setJobName();
1354
+			}
1355
+		}
1356
+		unset($this->setup->jobname);
1357
+
1358
+		if (!isset($this->meta->username))
1359
+		{
1360
+			self::setUserName();
1361
+		}
1362
+
1363
+		if (!isset($this->meta->fidelity))
1364
+		{
1365
+			$this->meta->fidelity = '';
1366
+		}
1367
+
1368
+		if (!isset($this->meta->document_name))
1369
+		{
1370
+			$this->meta->document_name = '';
1371
+		}
1372
+
1373
+		if (!isset($this->meta->sides))
1374
+		{
1375
+			$this->meta->sides = '';
1376
+		}
1377
+
1378
+		if (!isset($this->meta->page_ranges))
1379
+		{
1380
+			$this->meta->page_ranges = '';
1381
+		}
1382
+
1383
+		$jobattributes = '';
1384
+		$operationattributes = '';
1385
+		$printerattributes = '';
1386
+		self::_buildValues($operationattributes,$jobattributes,$printerattributes);
1387
+
1388
+		self::_setOperationId();
1389
+
1390
+		if (!isset($this->error_generation->request_body_malformed))
1391
+		{
1392
+			$this->error_generation->request_body_malformed = "";
1393
+		}
1394
+
1395
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1396
+						 . chr(0x00) . chr (0x03) // Print-URI | operation-id
1397
+						 . $this->meta->operation_id //           request-id
1398
+						 . $this->error_generation->request_body_malformed
1399
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
1400
+						 . $this->meta->charset
1401
+						 . $this->meta->language
1402
+						 . $this->meta->printer_uri
1403
+						 . $this->meta->jobname
1404
+						 . $this->meta->username
1405
+						 . $this->meta->fidelity
1406
+						 . $this->meta->document_name
1407
+						 . $this->meta->document_uri
1408
+						 . $operationattributes
1409
+						 . chr(0x02) // start job-attributes | job-attributes-tag
1410
+						 . $this->meta->copies
1411
+						 . $this->meta->sides
1412
+						 . $this->meta->page_ranges
1413
+						 . $jobattributes
1414
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
1415
+
1416
+		self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1417
+		return TRUE;
1418
+	}
1419
+
1420
+
1421
+	protected function _stringDocument ($job,$is_last)
1422
+	{
1423
+		if ($is_last == false)
1424
+		{
1425
+			$is_last = chr(0x00);
1426
+		}
1427
+		else
1428
+		{
1429
+			$is_last = chr(0x01);
1430
+		}
1431
+
1432
+		if (!isset($this->setup->charset))
1433
+		{
1434
+			self::setCharset();
1435
+		}
1436
+		if (!isset($this->setup->datatype))
1437
+		{
1438
+			self::setBinary();
1439
+		}
1440
+
1441
+		if (!isset($this->setup->uri))
1442
+		{
1443
+			$this->getPrinters();
1444
+			unset($this->jobs[count($this->jobs) - 1]);
1445
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
1446
+			unset($this->status[count($this->status) - 1]);
1447
+
1448
+			if (array_key_exists(0,$this->available_printers))
1449
+			{
1450
+			   self::setPrinterURI($this->available_printers[0]);
1451
+			}
1452
+			else
1453
+			{
1454
+				trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
1455
+				self::_putDebug( _("_stringJob: Printer URI is not set: die\n"));
1456
+				self::_errorLog(" Printer URI is not set, die",2);
1457
+				return FALSE;
1458
+				}
1459
+			}
1460
+
1461
+		if (!isset($this->setup->copies))
1462
+		{
1463
+			$this->meta->copies = "";
1464
+		}
1465
+
1466
+		if (!isset($this->setup->language))
1467
+		{
1468
+			self::setLanguage('en_us');
1469
+		}
1470
+
1471
+		if (!isset($this->setup->mime_media_type))
1472
+		{
1473
+			$this->meta->mime_media_type = "";
1474
+		}
1475
+		if ($this->setup->datatype != "TEXT")
1476
+		{
1477
+		unset ($this->setup->mime_media_type);
1478
+		}
1479
+
1480
+		if (!isset($this->meta->fidelity))
1481
+		{
1482
+			$this->meta->fidelity = '';
1483
+		}
1484
+
1485
+		if (!isset($this->meta->document_name))
1486
+		{
1487
+			$this->meta->document_name = '';
1488
+		}
1489
+
1490
+		if (!isset($this->meta->sides))
1491
+		{
1492
+			$this->meta->sides = '';
1493
+		}
1494
+
1495
+		if (!isset($this->meta->page_ranges))
1496
+		{
1497
+			$this->meta->page_ranges = '';
1498
+		}
1499
+
1500
+		$operationattributes = '';
1501
+		$jobattributes = '';
1502
+		$printerattributes = '';
1503
+		self::_buildValues($operationattributes,$jobattributes,$printerattributes);
1504
+
1505
+		self::_setOperationId();
1506
+
1507
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1508
+						 . chr(0x00) . chr (0x06) // Send-Document | operation-id
1509
+						 . $this->meta->operation_id //           request-id
1510
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
1511
+						 . $this->meta->charset
1512
+						 . $this->meta->language
1513
+						 . chr(0x45) // attribute-type: uri
1514
+						 . self::_giveMeStringLength("job-uri")
1515
+						 . "job-uri"
1516
+						 . self::_giveMeStringLength($job)
1517
+						 . $job
1518
+						 . $this->meta->username
1519
+						 . $this->meta->document_name
1520
+						 . $this->meta->fidelity
1521
+						 . $this->meta->mime_media_type
1522
+						 . $operationattributes
1523
+						 . chr(0x22) // boolean
1524
+						 . self::_giveMeStringLength("last-document")
1525
+						 . "last-document"
1526
+						 . self::_giveMeStringLength($is_last)
1527
+						 . $is_last
1528
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
1529
+
1530
+		self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1531
+		return TRUE;
1532
+	}
1533
+
1534
+
1535
+	protected function _stringSendUri ($uri,$job,$is_last)
1536
+	{
1537
+		$this->document_uri = $uri;
1538
+		self::_setDocumentUri();
1539
+
1540
+		if (!isset($this->setup->document_uri))
1541
+		{
1542
+			trigger_error(_("_stringUri: Document URI is not set: die"),E_USER_WARNING);
1543
+			self::_putDebug( _("_stringUri: Document URI is not set: die\n"));
1544
+			self::_errorLog("Document URI is not set, die",2);
1545
+			return FALSE;
1546
+		}
1547
+		unset ($this->setup->document_uri);
1548
+
1549
+		if ($is_last == false)
1550
+		{
1551
+			$is_last = chr(0x00);
1552
+		}
1553
+		else
1554
+		{
1555
+			$is_last = chr(0x01);
1556
+		}
1557
+
1558
+		if (!isset($this->setup->charset))
1559
+		{
1560
+			self::setCharset();
1561
+		}
1562
+		if (!isset($this->setup->datatype))
1563
+		{
1564
+			self::setBinary();
1565
+		}
1566
+
1567
+		if (!isset($this->setup->uri))
1568
+		{
1569
+			$this->getPrinters();
1570
+			unset($this->jobs[count($this->jobs) - 1]);
1571
+			unset($this->jobs_uri[count($this->jobs_uri) - 1]);
1572
+			unset($this->status[count($this->status) - 1]);
1573
+
1574
+			if (array_key_exists(0,$this->available_printers))
1575
+			{
1576
+			   self::setPrinterURI($this->available_printers[0]);
1577
+			} 
1578
+			else
1579
+			{
1580
+				trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
1581
+				self::_putDebug( _("_stringJob: Printer URI is not set: die\n"));
1582
+				self::_errorLog(" Printer URI is not set, die",2);
1583
+				return FALSE;
1584
+				}
1585
+			}
1586
+
1587
+		if (!isset($this->setup->copies))
1588
+		{
1589
+			$this->meta->copies = "";
1590
+		}
1591
+
1592
+		if (!isset($this->setup->language))
1593
+		{
1594
+			self::setLanguage('en_us');
1595
+		}
1596
+
1597
+		if (!isset($this->setup->mime_media_type))
1598
+		{
1599
+			$this->meta->mime_media_type = "";
1600
+		}
1601
+		unset ($this->setup->mime_media_type);
1602
+
1603
+		if (!isset($this->meta->fidelity))
1604
+		{
1605
+			$this->meta->fidelity = '';
1606
+		}
1607
+
1608
+		if (!isset($this->meta->document_name))
1609
+		{
1610
+			$this->meta->document_name = '';
1611
+		}
1612
+
1613
+		if (!isset($this->meta->sides))
1614
+		{
1615
+			$this->meta->sides = '';
1616
+		}
1617
+
1618
+		if (!isset($this->meta->page_ranges))
1619
+		{
1620
+			$this->meta->page_ranges = '';
1621
+		}
1622
+
1623
+		$operationattributes = '';
1624
+		$jobattributes = '';
1625
+		$printerattributes = '';
1626
+		self::_buildValues($operationattributes,$jobattributes,$printerattributes);
1627
+
1628
+		self::_setOperationId();
1629
+
1630
+		$this->stringjob = chr(0x01) . chr(0x01) // 1.1  | version-number
1631
+						 . chr(0x00) . chr (0x07) // Send-Uri | operation-id
1632
+						 . $this->meta->operation_id //           request-id
1633
+						 . chr(0x01) // start operation-attributes | operation-attributes-tag
1634
+						 . $this->meta->charset
1635
+						 . $this->meta->language
1636
+						 . chr(0x45) // attribute-type: uri
1637
+						 . self::_giveMeStringLength("job-uri")
1638
+						 . "job-uri"
1639
+						 . self::_giveMeStringLength($job)
1640
+						 . $job
1641
+						 . $this->meta->username
1642
+						 . $this->meta->document_uri
1643
+						 . $this->meta->fidelity
1644
+						 . $this->meta->mime_media_type
1645
+						 . $operationattributes
1646
+						 . chr(0x22) // boolean
1647
+						 . self::_giveMeStringLength("last-document")
1648
+						 . "last-document"
1649
+						 . self::_giveMeStringLength($is_last)
1650
+						 . $is_last
1651
+						 . chr(0x03); // end-of-attributes | end-of-attributes-tag
1652
+
1653
+		self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
1654
+		return TRUE;
1655
+	}
1656 1656
 }
1657 1657
\ No newline at end of file
Please login to merge, or discard this patch.
htdocs/includes/parsedown/Parsedown.php 1 patch
Indentation   +1641 added lines, -1641 removed lines patch added patch discarded remove patch
@@ -15,1698 +15,1698 @@
 block discarded – undo
15 15
 
16 16
 class Parsedown
17 17
 {
18
-    # ~
18
+	# ~
19 19
 
20
-    const version = '1.7.4';
21
-
22
-    # ~
23
-
24
-    function text($text)
25
-    {
26
-        # make sure no definitions are set
27
-        $this->DefinitionData = array();
28
-
29
-        # standardize line breaks
30
-        $text = str_replace(array("\r\n", "\r"), "\n", $text);
31
-
32
-        # remove surrounding line breaks
33
-        $text = trim($text, "\n");
34
-
35
-        # split text into lines
36
-        $lines = explode("\n", $text);
37
-
38
-        # iterate through lines to identify blocks
39
-        $markup = $this->lines($lines);
40
-
41
-        # trim line breaks
42
-        $markup = trim($markup, "\n");
43
-
44
-        return $markup;
45
-    }
46
-
47
-    #
48
-    # Setters
49
-    #
50
-
51
-    function setBreaksEnabled($breaksEnabled)
52
-    {
53
-        $this->breaksEnabled = $breaksEnabled;
54
-
55
-        return $this;
56
-    }
57
-
58
-    protected $breaksEnabled;
59
-
60
-    function setMarkupEscaped($markupEscaped)
61
-    {
62
-        $this->markupEscaped = $markupEscaped;
63
-
64
-        return $this;
65
-    }
66
-
67
-    protected $markupEscaped;
68
-
69
-    function setUrlsLinked($urlsLinked)
70
-    {
71
-        $this->urlsLinked = $urlsLinked;
72
-
73
-        return $this;
74
-    }
75
-
76
-    protected $urlsLinked = true;
77
-
78
-    function setSafeMode($safeMode)
79
-    {
80
-        $this->safeMode = (bool) $safeMode;
81
-
82
-        return $this;
83
-    }
84
-
85
-    protected $safeMode;
86
-
87
-    protected $safeLinksWhitelist = array(
88
-        'http://',
89
-        'https://',
90
-        'ftp://',
91
-        'ftps://',
92
-        'mailto:',
93
-        'data:image/png;base64,',
94
-        'data:image/gif;base64,',
95
-        'data:image/jpeg;base64,',
96
-        'irc:',
97
-        'ircs:',
98
-        'git:',
99
-        'ssh:',
100
-        'news:',
101
-        'steam:',
102
-    );
103
-
104
-    #
105
-    # Lines
106
-    #
107
-
108
-    protected $BlockTypes = array(
109
-        '#' => array('Header'),
110
-        '*' => array('Rule', 'List'),
111
-        '+' => array('List'),
112
-        '-' => array('SetextHeader', 'Table', 'Rule', 'List'),
113
-        '0' => array('List'),
114
-        '1' => array('List'),
115
-        '2' => array('List'),
116
-        '3' => array('List'),
117
-        '4' => array('List'),
118
-        '5' => array('List'),
119
-        '6' => array('List'),
120
-        '7' => array('List'),
121
-        '8' => array('List'),
122
-        '9' => array('List'),
123
-        ':' => array('Table'),
124
-        '<' => array('Comment', 'Markup'),
125
-        '=' => array('SetextHeader'),
126
-        '>' => array('Quote'),
127
-        '[' => array('Reference'),
128
-        '_' => array('Rule'),
129
-        '`' => array('FencedCode'),
130
-        '|' => array('Table'),
131
-        '~' => array('FencedCode'),
132
-    );
133
-
134
-    # ~
135
-
136
-    protected $unmarkedBlockTypes = array(
137
-        'Code',
138
-    );
139
-
140
-    #
141
-    # Blocks
142
-    #
143
-
144
-    protected function lines(array $lines)
145
-    {
146
-        $CurrentBlock = null;
147
-
148
-        foreach ($lines as $line)
149
-        {
150
-            if (chop($line) === '')
151
-            {
152
-                if (isset($CurrentBlock))
153
-                {
154
-                    $CurrentBlock['interrupted'] = true;
155
-                }
156
-
157
-                continue;
158
-            }
159
-
160
-            if (strpos($line, "\t") !== false)
161
-            {
162
-                $parts = explode("\t", $line);
163
-
164
-                $line = $parts[0];
165
-
166
-                unset($parts[0]);
167
-
168
-                foreach ($parts as $part)
169
-                {
170
-                    $shortage = 4 - mb_strlen($line, 'utf-8') % 4;
171
-
172
-                    $line .= str_repeat(' ', $shortage);
173
-                    $line .= $part;
174
-                }
175
-            }
176
-
177
-            $indent = 0;
178
-
179
-            while (isset($line[$indent]) and $line[$indent] === ' ')
180
-            {
181
-                $indent ++;
182
-            }
183
-
184
-            $text = $indent > 0 ? substr($line, $indent) : $line;
185
-
186
-            # ~
187
-
188
-            $Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
189
-
190
-            # ~
191
-
192
-            if (isset($CurrentBlock['continuable']))
193
-            {
194
-                $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);
195
-
196
-                if (isset($Block))
197
-                {
198
-                    $CurrentBlock = $Block;
199
-
200
-                    continue;
201
-                }
202
-                else
203
-                {
204
-                    if ($this->isBlockCompletable($CurrentBlock['type']))
205
-                    {
206
-                        $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
207
-                    }
208
-                }
209
-            }
20
+	const version = '1.7.4';
21
+
22
+	# ~
23
+
24
+	function text($text)
25
+	{
26
+		# make sure no definitions are set
27
+		$this->DefinitionData = array();
28
+
29
+		# standardize line breaks
30
+		$text = str_replace(array("\r\n", "\r"), "\n", $text);
31
+
32
+		# remove surrounding line breaks
33
+		$text = trim($text, "\n");
34
+
35
+		# split text into lines
36
+		$lines = explode("\n", $text);
37
+
38
+		# iterate through lines to identify blocks
39
+		$markup = $this->lines($lines);
40
+
41
+		# trim line breaks
42
+		$markup = trim($markup, "\n");
43
+
44
+		return $markup;
45
+	}
46
+
47
+	#
48
+	# Setters
49
+	#
50
+
51
+	function setBreaksEnabled($breaksEnabled)
52
+	{
53
+		$this->breaksEnabled = $breaksEnabled;
54
+
55
+		return $this;
56
+	}
57
+
58
+	protected $breaksEnabled;
59
+
60
+	function setMarkupEscaped($markupEscaped)
61
+	{
62
+		$this->markupEscaped = $markupEscaped;
63
+
64
+		return $this;
65
+	}
66
+
67
+	protected $markupEscaped;
68
+
69
+	function setUrlsLinked($urlsLinked)
70
+	{
71
+		$this->urlsLinked = $urlsLinked;
72
+
73
+		return $this;
74
+	}
75
+
76
+	protected $urlsLinked = true;
77
+
78
+	function setSafeMode($safeMode)
79
+	{
80
+		$this->safeMode = (bool) $safeMode;
81
+
82
+		return $this;
83
+	}
84
+
85
+	protected $safeMode;
86
+
87
+	protected $safeLinksWhitelist = array(
88
+		'http://',
89
+		'https://',
90
+		'ftp://',
91
+		'ftps://',
92
+		'mailto:',
93
+		'data:image/png;base64,',
94
+		'data:image/gif;base64,',
95
+		'data:image/jpeg;base64,',
96
+		'irc:',
97
+		'ircs:',
98
+		'git:',
99
+		'ssh:',
100
+		'news:',
101
+		'steam:',
102
+	);
103
+
104
+	#
105
+	# Lines
106
+	#
107
+
108
+	protected $BlockTypes = array(
109
+		'#' => array('Header'),
110
+		'*' => array('Rule', 'List'),
111
+		'+' => array('List'),
112
+		'-' => array('SetextHeader', 'Table', 'Rule', 'List'),
113
+		'0' => array('List'),
114
+		'1' => array('List'),
115
+		'2' => array('List'),
116
+		'3' => array('List'),
117
+		'4' => array('List'),
118
+		'5' => array('List'),
119
+		'6' => array('List'),
120
+		'7' => array('List'),
121
+		'8' => array('List'),
122
+		'9' => array('List'),
123
+		':' => array('Table'),
124
+		'<' => array('Comment', 'Markup'),
125
+		'=' => array('SetextHeader'),
126
+		'>' => array('Quote'),
127
+		'[' => array('Reference'),
128
+		'_' => array('Rule'),
129
+		'`' => array('FencedCode'),
130
+		'|' => array('Table'),
131
+		'~' => array('FencedCode'),
132
+	);
133
+
134
+	# ~
135
+
136
+	protected $unmarkedBlockTypes = array(
137
+		'Code',
138
+	);
139
+
140
+	#
141
+	# Blocks
142
+	#
143
+
144
+	protected function lines(array $lines)
145
+	{
146
+		$CurrentBlock = null;
147
+
148
+		foreach ($lines as $line)
149
+		{
150
+			if (chop($line) === '')
151
+			{
152
+				if (isset($CurrentBlock))
153
+				{
154
+					$CurrentBlock['interrupted'] = true;
155
+				}
156
+
157
+				continue;
158
+			}
159
+
160
+			if (strpos($line, "\t") !== false)
161
+			{
162
+				$parts = explode("\t", $line);
163
+
164
+				$line = $parts[0];
165
+
166
+				unset($parts[0]);
167
+
168
+				foreach ($parts as $part)
169
+				{
170
+					$shortage = 4 - mb_strlen($line, 'utf-8') % 4;
171
+
172
+					$line .= str_repeat(' ', $shortage);
173
+					$line .= $part;
174
+				}
175
+			}
176
+
177
+			$indent = 0;
178
+
179
+			while (isset($line[$indent]) and $line[$indent] === ' ')
180
+			{
181
+				$indent ++;
182
+			}
183
+
184
+			$text = $indent > 0 ? substr($line, $indent) : $line;
185
+
186
+			# ~
187
+
188
+			$Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
189
+
190
+			# ~
191
+
192
+			if (isset($CurrentBlock['continuable']))
193
+			{
194
+				$Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);
195
+
196
+				if (isset($Block))
197
+				{
198
+					$CurrentBlock = $Block;
199
+
200
+					continue;
201
+				}
202
+				else
203
+				{
204
+					if ($this->isBlockCompletable($CurrentBlock['type']))
205
+					{
206
+						$CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
207
+					}
208
+				}
209
+			}
210 210
 
211
-            # ~
211
+			# ~
212 212
 
213
-            $marker = $text[0];
213
+			$marker = $text[0];
214 214
 
215
-            # ~
215
+			# ~
216 216
 
217
-            $blockTypes = $this->unmarkedBlockTypes;
217
+			$blockTypes = $this->unmarkedBlockTypes;
218 218
 
219
-            if (isset($this->BlockTypes[$marker]))
220
-            {
221
-                foreach ($this->BlockTypes[$marker] as $blockType)
222
-                {
223
-                    $blockTypes []= $blockType;
224
-                }
225
-            }
219
+			if (isset($this->BlockTypes[$marker]))
220
+			{
221
+				foreach ($this->BlockTypes[$marker] as $blockType)
222
+				{
223
+					$blockTypes []= $blockType;
224
+				}
225
+			}
226 226
 
227
-            #
228
-            # ~
227
+			#
228
+			# ~
229 229
 
230
-            foreach ($blockTypes as $blockType)
231
-            {
232
-                $Block = $this->{'block'.$blockType}($Line, $CurrentBlock);
230
+			foreach ($blockTypes as $blockType)
231
+			{
232
+				$Block = $this->{'block'.$blockType}($Line, $CurrentBlock);
233 233
 
234
-                if (isset($Block))
235
-                {
236
-                    $Block['type'] = $blockType;
234
+				if (isset($Block))
235
+				{
236
+					$Block['type'] = $blockType;
237 237
 
238
-                    if ( ! isset($Block['identified']))
239
-                    {
240
-                        $Blocks []= $CurrentBlock;
238
+					if ( ! isset($Block['identified']))
239
+					{
240
+						$Blocks []= $CurrentBlock;
241 241
 
242
-                        $Block['identified'] = true;
243
-                    }
242
+						$Block['identified'] = true;
243
+					}
244 244
 
245
-                    if ($this->isBlockContinuable($blockType))
246
-                    {
247
-                        $Block['continuable'] = true;
248
-                    }
245
+					if ($this->isBlockContinuable($blockType))
246
+					{
247
+						$Block['continuable'] = true;
248
+					}
249 249
 
250
-                    $CurrentBlock = $Block;
250
+					$CurrentBlock = $Block;
251 251
 
252
-                    continue 2;
253
-                }
254
-            }
252
+					continue 2;
253
+				}
254
+			}
255 255
 
256
-            # ~
256
+			# ~
257 257
 
258
-            if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))
259
-            {
260
-                $CurrentBlock['element']['text'] .= "\n".$text;
261
-            }
262
-            else
263
-            {
264
-                $Blocks []= $CurrentBlock;
258
+			if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))
259
+			{
260
+				$CurrentBlock['element']['text'] .= "\n".$text;
261
+			}
262
+			else
263
+			{
264
+				$Blocks []= $CurrentBlock;
265 265
 
266
-                $CurrentBlock = $this->paragraph($Line);
266
+				$CurrentBlock = $this->paragraph($Line);
267 267
 
268
-                $CurrentBlock['identified'] = true;
269
-            }
270
-        }
268
+				$CurrentBlock['identified'] = true;
269
+			}
270
+		}
271 271
 
272
-        # ~
272
+		# ~
273 273
 
274
-        if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type']))
275
-        {
276
-            $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
277
-        }
274
+		if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type']))
275
+		{
276
+			$CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);
277
+		}
278 278
 
279
-        # ~
279
+		# ~
280 280
 
281
-        $Blocks []= $CurrentBlock;
281
+		$Blocks []= $CurrentBlock;
282 282
 
283
-        unset($Blocks[0]);
283
+		unset($Blocks[0]);
284 284
 
285
-        # ~
285
+		# ~
286 286
 
287
-        $markup = '';
287
+		$markup = '';
288 288
 
289
-        foreach ($Blocks as $Block)
290
-        {
291
-            if (isset($Block['hidden']))
292
-            {
293
-                continue;
294
-            }
289
+		foreach ($Blocks as $Block)
290
+		{
291
+			if (isset($Block['hidden']))
292
+			{
293
+				continue;
294
+			}
295 295
 
296
-            $markup .= "\n";
297
-            $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
298
-        }
296
+			$markup .= "\n";
297
+			$markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
298
+		}
299 299
 
300
-        $markup .= "\n";
300
+		$markup .= "\n";
301 301
 
302
-        # ~
302
+		# ~
303 303
 
304
-        return $markup;
305
-    }
304
+		return $markup;
305
+	}
306 306
 
307
-    protected function isBlockContinuable($Type)
308
-    {
309
-        return method_exists($this, 'block'.$Type.'Continue');
310
-    }
307
+	protected function isBlockContinuable($Type)
308
+	{
309
+		return method_exists($this, 'block'.$Type.'Continue');
310
+	}
311 311
 
312
-    protected function isBlockCompletable($Type)
313
-    {
314
-        return method_exists($this, 'block'.$Type.'Complete');
315
-    }
312
+	protected function isBlockCompletable($Type)
313
+	{
314
+		return method_exists($this, 'block'.$Type.'Complete');
315
+	}
316 316
 
317
-    #
318
-    # Code
317
+	#
318
+	# Code
319 319
 
320
-    protected function blockCode($Line, $Block = null)
321
-    {
322
-        if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))
323
-        {
324
-            return;
325
-        }
320
+	protected function blockCode($Line, $Block = null)
321
+	{
322
+		if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))
323
+		{
324
+			return;
325
+		}
326 326
 
327
-        if ($Line['indent'] >= 4)
328
-        {
329
-            $text = substr($Line['body'], 4);
327
+		if ($Line['indent'] >= 4)
328
+		{
329
+			$text = substr($Line['body'], 4);
330 330
 
331
-            $Block = array(
332
-                'element' => array(
333
-                    'name' => 'pre',
334
-                    'handler' => 'element',
335
-                    'text' => array(
336
-                        'name' => 'code',
337
-                        'text' => $text,
338
-                    ),
339
-                ),
340
-            );
341
-
342
-            return $Block;
343
-        }
344
-    }
345
-
346
-    protected function blockCodeContinue($Line, $Block)
347
-    {
348
-        if ($Line['indent'] >= 4)
349
-        {
350
-            if (isset($Block['interrupted']))
351
-            {
352
-                $Block['element']['text']['text'] .= "\n";
353
-
354
-                unset($Block['interrupted']);
355
-            }
356
-
357
-            $Block['element']['text']['text'] .= "\n";
358
-
359
-            $text = substr($Line['body'], 4);
360
-
361
-            $Block['element']['text']['text'] .= $text;
362
-
363
-            return $Block;
364
-        }
365
-    }
366
-
367
-    protected function blockCodeComplete($Block)
368
-    {
369
-        $text = $Block['element']['text']['text'];
370
-
371
-        $Block['element']['text']['text'] = $text;
372
-
373
-        return $Block;
374
-    }
375
-
376
-    #
377
-    # Comment
378
-
379
-    protected function blockComment($Line)
380
-    {
381
-        if ($this->markupEscaped or $this->safeMode)
382
-        {
383
-            return;
384
-        }
385
-
386
-        if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
387
-        {
388
-            $Block = array(
389
-                'markup' => $Line['body'],
390
-            );
391
-
392
-            if (preg_match('/-->$/', $Line['text']))
393
-            {
394
-                $Block['closed'] = true;
395
-            }
396
-
397
-            return $Block;
398
-        }
399
-    }
400
-
401
-    protected function blockCommentContinue($Line, array $Block)
402
-    {
403
-        if (isset($Block['closed']))
404
-        {
405
-            return;
406
-        }
407
-
408
-        $Block['markup'] .= "\n" . $Line['body'];
409
-
410
-        if (preg_match('/-->$/', $Line['text']))
411
-        {
412
-            $Block['closed'] = true;
413
-        }
414
-
415
-        return $Block;
416
-    }
417
-
418
-    #
419
-    # Fenced Code
420
-
421
-    protected function blockFencedCode($Line)
422
-    {
423
-        if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([^`]+)?[ ]*$/', $Line['text'], $matches))
424
-        {
425
-            $Element = array(
426
-                'name' => 'code',
427
-                'text' => '',
428
-            );
429
-
430
-            if (isset($matches[1]))
431
-            {
432
-                /**
433
-                 * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes
434
-                 * Every HTML element may have a class attribute specified.
435
-                 * The attribute, if specified, must have a value that is a set
436
-                 * of space-separated tokens representing the various classes
437
-                 * that the element belongs to.
438
-                 * [...]
439
-                 * The space characters, for the purposes of this specification,
440
-                 * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab),
441
-                 * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and
442
-                 * U+000D CARRIAGE RETURN (CR).
443
-                 */
444
-                $language = substr($matches[1], 0, strcspn($matches[1], " \t\n\f\r"));
445
-
446
-                $class = 'language-'.$language;
447
-
448
-                $Element['attributes'] = array(
449
-                    'class' => $class,
450
-                );
451
-            }
452
-
453
-            $Block = array(
454
-                'char' => $Line['text'][0],
455
-                'element' => array(
456
-                    'name' => 'pre',
457
-                    'handler' => 'element',
458
-                    'text' => $Element,
459
-                ),
460
-            );
461
-
462
-            return $Block;
463
-        }
464
-    }
465
-
466
-    protected function blockFencedCodeContinue($Line, $Block)
467
-    {
468
-        if (isset($Block['complete']))
469
-        {
470
-            return;
471
-        }
472
-
473
-        if (isset($Block['interrupted']))
474
-        {
475
-            $Block['element']['text']['text'] .= "\n";
476
-
477
-            unset($Block['interrupted']);
478
-        }
479
-
480
-        if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
481
-        {
482
-            $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);
483
-
484
-            $Block['complete'] = true;
485
-
486
-            return $Block;
487
-        }
488
-
489
-        $Block['element']['text']['text'] .= "\n".$Line['body'];
490
-
491
-        return $Block;
492
-    }
493
-
494
-    protected function blockFencedCodeComplete($Block)
495
-    {
496
-        $text = $Block['element']['text']['text'];
497
-
498
-        $Block['element']['text']['text'] = $text;
499
-
500
-        return $Block;
501
-    }
502
-
503
-    #
504
-    # Header
505
-
506
-    protected function blockHeader($Line)
507
-    {
508
-        if (isset($Line['text'][1]))
509
-        {
510
-            $level = 1;
511
-
512
-            while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
513
-            {
514
-                $level ++;
515
-            }
516
-
517
-            if ($level > 6)
518
-            {
519
-                return;
520
-            }
521
-
522
-            $text = trim($Line['text'], '# ');
523
-
524
-            $Block = array(
525
-                'element' => array(
526
-                    'name' => 'h' . min(6, $level),
527
-                    'text' => $text,
528
-                    'handler' => 'line',
529
-                ),
530
-            );
531
-
532
-            return $Block;
533
-        }
534
-    }
535
-
536
-    #
537
-    # List
538
-
539
-    protected function blockList($Line)
540
-    {
541
-        list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
542
-
543
-        if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))
544
-        {
545
-            $Block = array(
546
-                'indent' => $Line['indent'],
547
-                'pattern' => $pattern,
548
-                'element' => array(
549
-                    'name' => $name,
550
-                    'handler' => 'elements',
551
-                ),
552
-            );
553
-
554
-            if($name === 'ol')
555
-            {
556
-                $listStart = stristr($matches[0], '.', true);
557
-
558
-                if($listStart !== '1')
559
-                {
560
-                    $Block['element']['attributes'] = array('start' => $listStart);
561
-                }
562
-            }
563
-
564
-            $Block['li'] = array(
565
-                'name' => 'li',
566
-                'handler' => 'li',
567
-                'text' => array(
568
-                    $matches[2],
569
-                ),
570
-            );
571
-
572
-            $Block['element']['text'] []= & $Block['li'];
573
-
574
-            return $Block;
575
-        }
576
-    }
577
-
578
-    protected function blockListContinue($Line, array $Block)
579
-    {
580
-        if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))
581
-        {
582
-            if (isset($Block['interrupted']))
583
-            {
584
-                $Block['li']['text'] []= '';
585
-
586
-                $Block['loose'] = true;
587
-
588
-                unset($Block['interrupted']);
589
-            }
590
-
591
-            unset($Block['li']);
592
-
593
-            $text = isset($matches[1]) ? $matches[1] : '';
594
-
595
-            $Block['li'] = array(
596
-                'name' => 'li',
597
-                'handler' => 'li',
598
-                'text' => array(
599
-                    $text,
600
-                ),
601
-            );
602
-
603
-            $Block['element']['text'] []= & $Block['li'];
604
-
605
-            return $Block;
606
-        }
607
-
608
-        if ($Line['text'][0] === '[' and $this->blockReference($Line))
609
-        {
610
-            return $Block;
611
-        }
612
-
613
-        if ( ! isset($Block['interrupted']))
614
-        {
615
-            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
616
-
617
-            $Block['li']['text'] []= $text;
618
-
619
-            return $Block;
620
-        }
621
-
622
-        if ($Line['indent'] > 0)
623
-        {
624
-            $Block['li']['text'] []= '';
625
-
626
-            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
627
-
628
-            $Block['li']['text'] []= $text;
629
-
630
-            unset($Block['interrupted']);
631
-
632
-            return $Block;
633
-        }
634
-    }
635
-
636
-    protected function blockListComplete(array $Block)
637
-    {
638
-        if (isset($Block['loose']))
639
-        {
640
-            foreach ($Block['element']['text'] as &$li)
641
-            {
642
-                if (end($li['text']) !== '')
643
-                {
644
-                    $li['text'] []= '';
645
-                }
646
-            }
647
-        }
648
-
649
-        return $Block;
650
-    }
651
-
652
-    #
653
-    # Quote
654
-
655
-    protected function blockQuote($Line)
656
-    {
657
-        if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
658
-        {
659
-            $Block = array(
660
-                'element' => array(
661
-                    'name' => 'blockquote',
662
-                    'handler' => 'lines',
663
-                    'text' => (array) $matches[1],
664
-                ),
665
-            );
666
-
667
-            return $Block;
668
-        }
669
-    }
670
-
671
-    protected function blockQuoteContinue($Line, array $Block)
672
-    {
673
-        if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
674
-        {
675
-            if (isset($Block['interrupted']))
676
-            {
677
-                $Block['element']['text'] []= '';
678
-
679
-                unset($Block['interrupted']);
680
-            }
681
-
682
-            $Block['element']['text'] []= $matches[1];
683
-
684
-            return $Block;
685
-        }
686
-
687
-        if ( ! isset($Block['interrupted']))
688
-        {
689
-            $Block['element']['text'] []= $Line['text'];
690
-
691
-            return $Block;
692
-        }
693
-    }
694
-
695
-    #
696
-    # Rule
697
-
698
-    protected function blockRule($Line)
699
-    {
700
-        if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text']))
701
-        {
702
-            $Block = array(
703
-                'element' => array(
704
-                    'name' => 'hr'
705
-                ),
706
-            );
707
-
708
-            return $Block;
709
-        }
710
-    }
711
-
712
-    #
713
-    # Setext
714
-
715
-    protected function blockSetextHeader($Line, array $Block = null)
716
-    {
717
-        if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
718
-        {
719
-            return;
720
-        }
721
-
722
-        if (chop($Line['text'], $Line['text'][0]) === '')
723
-        {
724
-            $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
725
-
726
-            return $Block;
727
-        }
728
-    }
729
-
730
-    #
731
-    # Markup
732
-
733
-    protected function blockMarkup($Line)
734
-    {
735
-        if ($this->markupEscaped or $this->safeMode)
736
-        {
737
-            return;
738
-        }
739
-
740
-        if (preg_match('/^<(\w[\w-]*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
741
-        {
742
-            $element = strtolower($matches[1]);
743
-
744
-            if (in_array($element, $this->textLevelElements))
745
-            {
746
-                return;
747
-            }
748
-
749
-            $Block = array(
750
-                'name' => $matches[1],
751
-                'depth' => 0,
752
-                'markup' => $Line['text'],
753
-            );
754
-
755
-            $length = strlen($matches[0]);
756
-
757
-            $remainder = substr($Line['text'], $length);
758
-
759
-            if (trim($remainder) === '')
760
-            {
761
-                if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
762
-                {
763
-                    $Block['closed'] = true;
764
-
765
-                    $Block['void'] = true;
766
-                }
767
-            }
768
-            else
769
-            {
770
-                if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
771
-                {
772
-                    return;
773
-                }
774
-
775
-                if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
776
-                {
777
-                    $Block['closed'] = true;
778
-                }
779
-            }
780
-
781
-            return $Block;
782
-        }
783
-    }
784
-
785
-    protected function blockMarkupContinue($Line, array $Block)
786
-    {
787
-        if (isset($Block['closed']))
788
-        {
789
-            return;
790
-        }
791
-
792
-        if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
793
-        {
794
-            $Block['depth'] ++;
795
-        }
796
-
797
-        if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
798
-        {
799
-            if ($Block['depth'] > 0)
800
-            {
801
-                $Block['depth'] --;
802
-            }
803
-            else
804
-            {
805
-                $Block['closed'] = true;
806
-            }
807
-        }
808
-
809
-        if (isset($Block['interrupted']))
810
-        {
811
-            $Block['markup'] .= "\n";
812
-
813
-            unset($Block['interrupted']);
814
-        }
815
-
816
-        $Block['markup'] .= "\n".$Line['body'];
817
-
818
-        return $Block;
819
-    }
820
-
821
-    #
822
-    # Reference
823
-
824
-    protected function blockReference($Line)
825
-    {
826
-        if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
827
-        {
828
-            $id = strtolower($matches[1]);
829
-
830
-            $Data = array(
831
-                'url' => $matches[2],
832
-                'title' => null,
833
-            );
834
-
835
-            if (isset($matches[3]))
836
-            {
837
-                $Data['title'] = $matches[3];
838
-            }
839
-
840
-            $this->DefinitionData['Reference'][$id] = $Data;
841
-
842
-            $Block = array(
843
-                'hidden' => true,
844
-            );
845
-
846
-            return $Block;
847
-        }
848
-    }
849
-
850
-    #
851
-    # Table
852
-
853
-    protected function blockTable($Line, array $Block = null)
854
-    {
855
-        if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
856
-        {
857
-            return;
858
-        }
859
-
860
-        if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')
861
-        {
862
-            $alignments = array();
863
-
864
-            $divider = $Line['text'];
865
-
866
-            $divider = trim($divider);
867
-            $divider = trim($divider, '|');
868
-
869
-            $dividerCells = explode('|', $divider);
870
-
871
-            foreach ($dividerCells as $dividerCell)
872
-            {
873
-                $dividerCell = trim($dividerCell);
874
-
875
-                if ($dividerCell === '')
876
-                {
877
-                    continue;
878
-                }
879
-
880
-                $alignment = null;
881
-
882
-                if ($dividerCell[0] === ':')
883
-                {
884
-                    $alignment = 'left';
885
-                }
886
-
887
-                if (substr($dividerCell, - 1) === ':')
888
-                {
889
-                    $alignment = $alignment === 'left' ? 'center' : 'right';
890
-                }
891
-
892
-                $alignments []= $alignment;
893
-            }
894
-
895
-            # ~
896
-
897
-            $HeaderElements = array();
898
-
899
-            $header = $Block['element']['text'];
900
-
901
-            $header = trim($header);
902
-            $header = trim($header, '|');
331
+			$Block = array(
332
+				'element' => array(
333
+					'name' => 'pre',
334
+					'handler' => 'element',
335
+					'text' => array(
336
+						'name' => 'code',
337
+						'text' => $text,
338
+					),
339
+				),
340
+			);
341
+
342
+			return $Block;
343
+		}
344
+	}
345
+
346
+	protected function blockCodeContinue($Line, $Block)
347
+	{
348
+		if ($Line['indent'] >= 4)
349
+		{
350
+			if (isset($Block['interrupted']))
351
+			{
352
+				$Block['element']['text']['text'] .= "\n";
353
+
354
+				unset($Block['interrupted']);
355
+			}
356
+
357
+			$Block['element']['text']['text'] .= "\n";
358
+
359
+			$text = substr($Line['body'], 4);
360
+
361
+			$Block['element']['text']['text'] .= $text;
362
+
363
+			return $Block;
364
+		}
365
+	}
366
+
367
+	protected function blockCodeComplete($Block)
368
+	{
369
+		$text = $Block['element']['text']['text'];
370
+
371
+		$Block['element']['text']['text'] = $text;
372
+
373
+		return $Block;
374
+	}
375
+
376
+	#
377
+	# Comment
378
+
379
+	protected function blockComment($Line)
380
+	{
381
+		if ($this->markupEscaped or $this->safeMode)
382
+		{
383
+			return;
384
+		}
385
+
386
+		if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
387
+		{
388
+			$Block = array(
389
+				'markup' => $Line['body'],
390
+			);
391
+
392
+			if (preg_match('/-->$/', $Line['text']))
393
+			{
394
+				$Block['closed'] = true;
395
+			}
396
+
397
+			return $Block;
398
+		}
399
+	}
400
+
401
+	protected function blockCommentContinue($Line, array $Block)
402
+	{
403
+		if (isset($Block['closed']))
404
+		{
405
+			return;
406
+		}
407
+
408
+		$Block['markup'] .= "\n" . $Line['body'];
409
+
410
+		if (preg_match('/-->$/', $Line['text']))
411
+		{
412
+			$Block['closed'] = true;
413
+		}
414
+
415
+		return $Block;
416
+	}
417
+
418
+	#
419
+	# Fenced Code
420
+
421
+	protected function blockFencedCode($Line)
422
+	{
423
+		if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([^`]+)?[ ]*$/', $Line['text'], $matches))
424
+		{
425
+			$Element = array(
426
+				'name' => 'code',
427
+				'text' => '',
428
+			);
429
+
430
+			if (isset($matches[1]))
431
+			{
432
+				/**
433
+				 * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes
434
+				 * Every HTML element may have a class attribute specified.
435
+				 * The attribute, if specified, must have a value that is a set
436
+				 * of space-separated tokens representing the various classes
437
+				 * that the element belongs to.
438
+				 * [...]
439
+				 * The space characters, for the purposes of this specification,
440
+				 * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab),
441
+				 * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and
442
+				 * U+000D CARRIAGE RETURN (CR).
443
+				 */
444
+				$language = substr($matches[1], 0, strcspn($matches[1], " \t\n\f\r"));
445
+
446
+				$class = 'language-'.$language;
447
+
448
+				$Element['attributes'] = array(
449
+					'class' => $class,
450
+				);
451
+			}
452
+
453
+			$Block = array(
454
+				'char' => $Line['text'][0],
455
+				'element' => array(
456
+					'name' => 'pre',
457
+					'handler' => 'element',
458
+					'text' => $Element,
459
+				),
460
+			);
461
+
462
+			return $Block;
463
+		}
464
+	}
465
+
466
+	protected function blockFencedCodeContinue($Line, $Block)
467
+	{
468
+		if (isset($Block['complete']))
469
+		{
470
+			return;
471
+		}
472
+
473
+		if (isset($Block['interrupted']))
474
+		{
475
+			$Block['element']['text']['text'] .= "\n";
476
+
477
+			unset($Block['interrupted']);
478
+		}
479
+
480
+		if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))
481
+		{
482
+			$Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);
483
+
484
+			$Block['complete'] = true;
485
+
486
+			return $Block;
487
+		}
488
+
489
+		$Block['element']['text']['text'] .= "\n".$Line['body'];
490
+
491
+		return $Block;
492
+	}
493
+
494
+	protected function blockFencedCodeComplete($Block)
495
+	{
496
+		$text = $Block['element']['text']['text'];
497
+
498
+		$Block['element']['text']['text'] = $text;
499
+
500
+		return $Block;
501
+	}
502
+
503
+	#
504
+	# Header
505
+
506
+	protected function blockHeader($Line)
507
+	{
508
+		if (isset($Line['text'][1]))
509
+		{
510
+			$level = 1;
511
+
512
+			while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')
513
+			{
514
+				$level ++;
515
+			}
516
+
517
+			if ($level > 6)
518
+			{
519
+				return;
520
+			}
521
+
522
+			$text = trim($Line['text'], '# ');
523
+
524
+			$Block = array(
525
+				'element' => array(
526
+					'name' => 'h' . min(6, $level),
527
+					'text' => $text,
528
+					'handler' => 'line',
529
+				),
530
+			);
531
+
532
+			return $Block;
533
+		}
534
+	}
535
+
536
+	#
537
+	# List
538
+
539
+	protected function blockList($Line)
540
+	{
541
+		list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
542
+
543
+		if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))
544
+		{
545
+			$Block = array(
546
+				'indent' => $Line['indent'],
547
+				'pattern' => $pattern,
548
+				'element' => array(
549
+					'name' => $name,
550
+					'handler' => 'elements',
551
+				),
552
+			);
553
+
554
+			if($name === 'ol')
555
+			{
556
+				$listStart = stristr($matches[0], '.', true);
557
+
558
+				if($listStart !== '1')
559
+				{
560
+					$Block['element']['attributes'] = array('start' => $listStart);
561
+				}
562
+			}
563
+
564
+			$Block['li'] = array(
565
+				'name' => 'li',
566
+				'handler' => 'li',
567
+				'text' => array(
568
+					$matches[2],
569
+				),
570
+			);
571
+
572
+			$Block['element']['text'] []= & $Block['li'];
573
+
574
+			return $Block;
575
+		}
576
+	}
577
+
578
+	protected function blockListContinue($Line, array $Block)
579
+	{
580
+		if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))
581
+		{
582
+			if (isset($Block['interrupted']))
583
+			{
584
+				$Block['li']['text'] []= '';
585
+
586
+				$Block['loose'] = true;
587
+
588
+				unset($Block['interrupted']);
589
+			}
590
+
591
+			unset($Block['li']);
592
+
593
+			$text = isset($matches[1]) ? $matches[1] : '';
594
+
595
+			$Block['li'] = array(
596
+				'name' => 'li',
597
+				'handler' => 'li',
598
+				'text' => array(
599
+					$text,
600
+				),
601
+			);
602
+
603
+			$Block['element']['text'] []= & $Block['li'];
604
+
605
+			return $Block;
606
+		}
607
+
608
+		if ($Line['text'][0] === '[' and $this->blockReference($Line))
609
+		{
610
+			return $Block;
611
+		}
612
+
613
+		if ( ! isset($Block['interrupted']))
614
+		{
615
+			$text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
616
+
617
+			$Block['li']['text'] []= $text;
618
+
619
+			return $Block;
620
+		}
621
+
622
+		if ($Line['indent'] > 0)
623
+		{
624
+			$Block['li']['text'] []= '';
625
+
626
+			$text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
627
+
628
+			$Block['li']['text'] []= $text;
629
+
630
+			unset($Block['interrupted']);
631
+
632
+			return $Block;
633
+		}
634
+	}
635
+
636
+	protected function blockListComplete(array $Block)
637
+	{
638
+		if (isset($Block['loose']))
639
+		{
640
+			foreach ($Block['element']['text'] as &$li)
641
+			{
642
+				if (end($li['text']) !== '')
643
+				{
644
+					$li['text'] []= '';
645
+				}
646
+			}
647
+		}
648
+
649
+		return $Block;
650
+	}
651
+
652
+	#
653
+	# Quote
654
+
655
+	protected function blockQuote($Line)
656
+	{
657
+		if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
658
+		{
659
+			$Block = array(
660
+				'element' => array(
661
+					'name' => 'blockquote',
662
+					'handler' => 'lines',
663
+					'text' => (array) $matches[1],
664
+				),
665
+			);
666
+
667
+			return $Block;
668
+		}
669
+	}
670
+
671
+	protected function blockQuoteContinue($Line, array $Block)
672
+	{
673
+		if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))
674
+		{
675
+			if (isset($Block['interrupted']))
676
+			{
677
+				$Block['element']['text'] []= '';
678
+
679
+				unset($Block['interrupted']);
680
+			}
681
+
682
+			$Block['element']['text'] []= $matches[1];
683
+
684
+			return $Block;
685
+		}
686
+
687
+		if ( ! isset($Block['interrupted']))
688
+		{
689
+			$Block['element']['text'] []= $Line['text'];
690
+
691
+			return $Block;
692
+		}
693
+	}
694
+
695
+	#
696
+	# Rule
697
+
698
+	protected function blockRule($Line)
699
+	{
700
+		if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text']))
701
+		{
702
+			$Block = array(
703
+				'element' => array(
704
+					'name' => 'hr'
705
+				),
706
+			);
707
+
708
+			return $Block;
709
+		}
710
+	}
711
+
712
+	#
713
+	# Setext
714
+
715
+	protected function blockSetextHeader($Line, array $Block = null)
716
+	{
717
+		if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
718
+		{
719
+			return;
720
+		}
721
+
722
+		if (chop($Line['text'], $Line['text'][0]) === '')
723
+		{
724
+			$Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
725
+
726
+			return $Block;
727
+		}
728
+	}
729
+
730
+	#
731
+	# Markup
732
+
733
+	protected function blockMarkup($Line)
734
+	{
735
+		if ($this->markupEscaped or $this->safeMode)
736
+		{
737
+			return;
738
+		}
739
+
740
+		if (preg_match('/^<(\w[\w-]*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
741
+		{
742
+			$element = strtolower($matches[1]);
743
+
744
+			if (in_array($element, $this->textLevelElements))
745
+			{
746
+				return;
747
+			}
748
+
749
+			$Block = array(
750
+				'name' => $matches[1],
751
+				'depth' => 0,
752
+				'markup' => $Line['text'],
753
+			);
754
+
755
+			$length = strlen($matches[0]);
756
+
757
+			$remainder = substr($Line['text'], $length);
758
+
759
+			if (trim($remainder) === '')
760
+			{
761
+				if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
762
+				{
763
+					$Block['closed'] = true;
764
+
765
+					$Block['void'] = true;
766
+				}
767
+			}
768
+			else
769
+			{
770
+				if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
771
+				{
772
+					return;
773
+				}
774
+
775
+				if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
776
+				{
777
+					$Block['closed'] = true;
778
+				}
779
+			}
780
+
781
+			return $Block;
782
+		}
783
+	}
784
+
785
+	protected function blockMarkupContinue($Line, array $Block)
786
+	{
787
+		if (isset($Block['closed']))
788
+		{
789
+			return;
790
+		}
791
+
792
+		if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
793
+		{
794
+			$Block['depth'] ++;
795
+		}
796
+
797
+		if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
798
+		{
799
+			if ($Block['depth'] > 0)
800
+			{
801
+				$Block['depth'] --;
802
+			}
803
+			else
804
+			{
805
+				$Block['closed'] = true;
806
+			}
807
+		}
808
+
809
+		if (isset($Block['interrupted']))
810
+		{
811
+			$Block['markup'] .= "\n";
812
+
813
+			unset($Block['interrupted']);
814
+		}
815
+
816
+		$Block['markup'] .= "\n".$Line['body'];
817
+
818
+		return $Block;
819
+	}
820
+
821
+	#
822
+	# Reference
823
+
824
+	protected function blockReference($Line)
825
+	{
826
+		if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
827
+		{
828
+			$id = strtolower($matches[1]);
829
+
830
+			$Data = array(
831
+				'url' => $matches[2],
832
+				'title' => null,
833
+			);
834
+
835
+			if (isset($matches[3]))
836
+			{
837
+				$Data['title'] = $matches[3];
838
+			}
839
+
840
+			$this->DefinitionData['Reference'][$id] = $Data;
841
+
842
+			$Block = array(
843
+				'hidden' => true,
844
+			);
845
+
846
+			return $Block;
847
+		}
848
+	}
849
+
850
+	#
851
+	# Table
852
+
853
+	protected function blockTable($Line, array $Block = null)
854
+	{
855
+		if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))
856
+		{
857
+			return;
858
+		}
859
+
860
+		if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')
861
+		{
862
+			$alignments = array();
863
+
864
+			$divider = $Line['text'];
865
+
866
+			$divider = trim($divider);
867
+			$divider = trim($divider, '|');
868
+
869
+			$dividerCells = explode('|', $divider);
870
+
871
+			foreach ($dividerCells as $dividerCell)
872
+			{
873
+				$dividerCell = trim($dividerCell);
874
+
875
+				if ($dividerCell === '')
876
+				{
877
+					continue;
878
+				}
879
+
880
+				$alignment = null;
881
+
882
+				if ($dividerCell[0] === ':')
883
+				{
884
+					$alignment = 'left';
885
+				}
886
+
887
+				if (substr($dividerCell, - 1) === ':')
888
+				{
889
+					$alignment = $alignment === 'left' ? 'center' : 'right';
890
+				}
891
+
892
+				$alignments []= $alignment;
893
+			}
894
+
895
+			# ~
896
+
897
+			$HeaderElements = array();
898
+
899
+			$header = $Block['element']['text'];
900
+
901
+			$header = trim($header);
902
+			$header = trim($header, '|');
903 903
 
904
-            $headerCells = explode('|', $header);
904
+			$headerCells = explode('|', $header);
905 905
 
906
-            foreach ($headerCells as $index => $headerCell)
907
-            {
908
-                $headerCell = trim($headerCell);
906
+			foreach ($headerCells as $index => $headerCell)
907
+			{
908
+				$headerCell = trim($headerCell);
909 909
 
910
-                $HeaderElement = array(
911
-                    'name' => 'th',
912
-                    'text' => $headerCell,
913
-                    'handler' => 'line',
914
-                );
910
+				$HeaderElement = array(
911
+					'name' => 'th',
912
+					'text' => $headerCell,
913
+					'handler' => 'line',
914
+				);
915 915
 
916
-                if (isset($alignments[$index]))
917
-                {
918
-                    $alignment = $alignments[$index];
919
-
920
-                    $HeaderElement['attributes'] = array(
921
-                        'style' => 'text-align: '.$alignment.';',
922
-                    );
923
-                }
924
-
925
-                $HeaderElements []= $HeaderElement;
926
-            }
927
-
928
-            # ~
929
-
930
-            $Block = array(
931
-                'alignments' => $alignments,
932
-                'identified' => true,
933
-                'element' => array(
934
-                    'name' => 'table',
935
-                    'handler' => 'elements',
936
-                ),
937
-            );
938
-
939
-            $Block['element']['text'] []= array(
940
-                'name' => 'thead',
941
-                'handler' => 'elements',
942
-            );
943
-
944
-            $Block['element']['text'] []= array(
945
-                'name' => 'tbody',
946
-                'handler' => 'elements',
947
-                'text' => array(),
948
-            );
949
-
950
-            $Block['element']['text'][0]['text'] []= array(
951
-                'name' => 'tr',
952
-                'handler' => 'elements',
953
-                'text' => $HeaderElements,
954
-            );
955
-
956
-            return $Block;
957
-        }
958
-    }
959
-
960
-    protected function blockTableContinue($Line, array $Block)
961
-    {
962
-        if (isset($Block['interrupted']))
963
-        {
964
-            return;
965
-        }
966
-
967
-        if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))
968
-        {
969
-            $Elements = array();
970
-
971
-            $row = $Line['text'];
972
-
973
-            $row = trim($row);
974
-            $row = trim($row, '|');
975
-
976
-            preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
977
-
978
-            foreach ($matches[0] as $index => $cell)
979
-            {
980
-                $cell = trim($cell);
981
-
982
-                $Element = array(
983
-                    'name' => 'td',
984
-                    'handler' => 'line',
985
-                    'text' => $cell,
986
-                );
987
-
988
-                if (isset($Block['alignments'][$index]))
989
-                {
990
-                    $Element['attributes'] = array(
991
-                        'style' => 'text-align: '.$Block['alignments'][$index].';',
992
-                    );
993
-                }
994
-
995
-                $Elements []= $Element;
996
-            }
997
-
998
-            $Element = array(
999
-                'name' => 'tr',
1000
-                'handler' => 'elements',
1001
-                'text' => $Elements,
1002
-            );
1003
-
1004
-            $Block['element']['text'][1]['text'] []= $Element;
1005
-
1006
-            return $Block;
1007
-        }
1008
-    }
1009
-
1010
-    #
1011
-    # ~
1012
-    #
1013
-
1014
-    protected function paragraph($Line)
1015
-    {
1016
-        $Block = array(
1017
-            'element' => array(
1018
-                'name' => 'p',
1019
-                'text' => $Line['text'],
1020
-                'handler' => 'line',
1021
-            ),
1022
-        );
916
+				if (isset($alignments[$index]))
917
+				{
918
+					$alignment = $alignments[$index];
919
+
920
+					$HeaderElement['attributes'] = array(
921
+						'style' => 'text-align: '.$alignment.';',
922
+					);
923
+				}
924
+
925
+				$HeaderElements []= $HeaderElement;
926
+			}
927
+
928
+			# ~
929
+
930
+			$Block = array(
931
+				'alignments' => $alignments,
932
+				'identified' => true,
933
+				'element' => array(
934
+					'name' => 'table',
935
+					'handler' => 'elements',
936
+				),
937
+			);
938
+
939
+			$Block['element']['text'] []= array(
940
+				'name' => 'thead',
941
+				'handler' => 'elements',
942
+			);
943
+
944
+			$Block['element']['text'] []= array(
945
+				'name' => 'tbody',
946
+				'handler' => 'elements',
947
+				'text' => array(),
948
+			);
949
+
950
+			$Block['element']['text'][0]['text'] []= array(
951
+				'name' => 'tr',
952
+				'handler' => 'elements',
953
+				'text' => $HeaderElements,
954
+			);
955
+
956
+			return $Block;
957
+		}
958
+	}
959
+
960
+	protected function blockTableContinue($Line, array $Block)
961
+	{
962
+		if (isset($Block['interrupted']))
963
+		{
964
+			return;
965
+		}
966
+
967
+		if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))
968
+		{
969
+			$Elements = array();
970
+
971
+			$row = $Line['text'];
972
+
973
+			$row = trim($row);
974
+			$row = trim($row, '|');
975
+
976
+			preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
977
+
978
+			foreach ($matches[0] as $index => $cell)
979
+			{
980
+				$cell = trim($cell);
981
+
982
+				$Element = array(
983
+					'name' => 'td',
984
+					'handler' => 'line',
985
+					'text' => $cell,
986
+				);
987
+
988
+				if (isset($Block['alignments'][$index]))
989
+				{
990
+					$Element['attributes'] = array(
991
+						'style' => 'text-align: '.$Block['alignments'][$index].';',
992
+					);
993
+				}
994
+
995
+				$Elements []= $Element;
996
+			}
997
+
998
+			$Element = array(
999
+				'name' => 'tr',
1000
+				'handler' => 'elements',
1001
+				'text' => $Elements,
1002
+			);
1003
+
1004
+			$Block['element']['text'][1]['text'] []= $Element;
1005
+
1006
+			return $Block;
1007
+		}
1008
+	}
1009
+
1010
+	#
1011
+	# ~
1012
+	#
1013
+
1014
+	protected function paragraph($Line)
1015
+	{
1016
+		$Block = array(
1017
+			'element' => array(
1018
+				'name' => 'p',
1019
+				'text' => $Line['text'],
1020
+				'handler' => 'line',
1021
+			),
1022
+		);
1023 1023
 
1024
-        return $Block;
1025
-    }
1024
+		return $Block;
1025
+	}
1026 1026
 
1027
-    #
1028
-    # Inline Elements
1029
-    #
1027
+	#
1028
+	# Inline Elements
1029
+	#
1030 1030
 
1031
-    protected $InlineTypes = array(
1032
-        '"' => array('SpecialCharacter'),
1033
-        '!' => array('Image'),
1034
-        '&' => array('SpecialCharacter'),
1035
-        '*' => array('Emphasis'),
1036
-        ':' => array('Url'),
1037
-        '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
1038
-        '>' => array('SpecialCharacter'),
1039
-        '[' => array('Link'),
1040
-        '_' => array('Emphasis'),
1041
-        '`' => array('Code'),
1042
-        '~' => array('Strikethrough'),
1043
-        '\\' => array('EscapeSequence'),
1044
-    );
1031
+	protected $InlineTypes = array(
1032
+		'"' => array('SpecialCharacter'),
1033
+		'!' => array('Image'),
1034
+		'&' => array('SpecialCharacter'),
1035
+		'*' => array('Emphasis'),
1036
+		':' => array('Url'),
1037
+		'<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
1038
+		'>' => array('SpecialCharacter'),
1039
+		'[' => array('Link'),
1040
+		'_' => array('Emphasis'),
1041
+		'`' => array('Code'),
1042
+		'~' => array('Strikethrough'),
1043
+		'\\' => array('EscapeSequence'),
1044
+	);
1045 1045
 
1046
-    # ~
1046
+	# ~
1047 1047
 
1048
-    protected $inlineMarkerList = '!"*_&[:<>`~\\';
1048
+	protected $inlineMarkerList = '!"*_&[:<>`~\\';
1049 1049
 
1050
-    #
1051
-    # ~
1052
-    #
1050
+	#
1051
+	# ~
1052
+	#
1053 1053
 
1054
-    public function line($text, $nonNestables=array())
1055
-    {
1056
-        $markup = '';
1054
+	public function line($text, $nonNestables=array())
1055
+	{
1056
+		$markup = '';
1057 1057
 
1058
-        # $excerpt is based on the first occurrence of a marker
1058
+		# $excerpt is based on the first occurrence of a marker
1059 1059
 
1060
-        while ($excerpt = strpbrk($text, $this->inlineMarkerList))
1061
-        {
1062
-            $marker = $excerpt[0];
1060
+		while ($excerpt = strpbrk($text, $this->inlineMarkerList))
1061
+		{
1062
+			$marker = $excerpt[0];
1063 1063
 
1064
-            $markerPosition = strpos($text, $marker);
1064
+			$markerPosition = strpos($text, $marker);
1065 1065
 
1066
-            $Excerpt = array('text' => $excerpt, 'context' => $text);
1066
+			$Excerpt = array('text' => $excerpt, 'context' => $text);
1067 1067
 
1068
-            foreach ($this->InlineTypes[$marker] as $inlineType)
1069
-            {
1070
-                # check to see if the current inline type is nestable in the current context
1068
+			foreach ($this->InlineTypes[$marker] as $inlineType)
1069
+			{
1070
+				# check to see if the current inline type is nestable in the current context
1071 1071
 
1072
-                if ( ! empty($nonNestables) and in_array($inlineType, $nonNestables))
1073
-                {
1074
-                    continue;
1075
-                }
1076
-
1077
-                $Inline = $this->{'inline'.$inlineType}($Excerpt);
1078
-
1079
-                if ( ! isset($Inline))
1080
-                {
1081
-                    continue;
1082
-                }
1083
-
1084
-                # makes sure that the inline belongs to "our" marker
1085
-
1086
-                if (isset($Inline['position']) and $Inline['position'] > $markerPosition)
1087
-                {
1088
-                    continue;
1089
-                }
1090
-
1091
-                # sets a default inline position
1092
-
1093
-                if ( ! isset($Inline['position']))
1094
-                {
1095
-                    $Inline['position'] = $markerPosition;
1096
-                }
1097
-
1098
-                # cause the new element to 'inherit' our non nestables
1099
-
1100
-                foreach ($nonNestables as $non_nestable)
1101
-                {
1102
-                    $Inline['element']['nonNestables'][] = $non_nestable;
1103
-                }
1104
-
1105
-                # the text that comes before the inline
1106
-                $unmarkedText = substr($text, 0, $Inline['position']);
1107
-
1108
-                # compile the unmarked text
1109
-                $markup .= $this->unmarkedText($unmarkedText);
1110
-
1111
-                # compile the inline
1112
-                $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
1113
-
1114
-                # remove the examined text
1115
-                $text = substr($text, $Inline['position'] + $Inline['extent']);
1116
-
1117
-                continue 2;
1118
-            }
1119
-
1120
-            # the marker does not belong to an inline
1121
-
1122
-            $unmarkedText = substr($text, 0, $markerPosition + 1);
1123
-
1124
-            $markup .= $this->unmarkedText($unmarkedText);
1125
-
1126
-            $text = substr($text, $markerPosition + 1);
1127
-        }
1128
-
1129
-        $markup .= $this->unmarkedText($text);
1130
-
1131
-        return $markup;
1132
-    }
1133
-
1134
-    #
1135
-    # ~
1136
-    #
1137
-
1138
-    protected function inlineCode($Excerpt)
1139
-    {
1140
-        $marker = $Excerpt['text'][0];
1141
-
1142
-        if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
1143
-        {
1144
-            $text = $matches[2];
1145
-            $text = preg_replace("/[ ]*\n/", ' ', $text);
1146
-
1147
-            return array(
1148
-                'extent' => strlen($matches[0]),
1149
-                'element' => array(
1150
-                    'name' => 'code',
1151
-                    'text' => $text,
1152
-                ),
1153
-            );
1154
-        }
1155
-    }
1156
-
1157
-    protected function inlineEmailTag($Excerpt)
1158
-    {
1159
-        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
1160
-        {
1161
-            $url = $matches[1];
1162
-
1163
-            if ( ! isset($matches[2]))
1164
-            {
1165
-                $url = 'mailto:' . $url;
1166
-            }
1167
-
1168
-            return array(
1169
-                'extent' => strlen($matches[0]),
1170
-                'element' => array(
1171
-                    'name' => 'a',
1172
-                    'text' => $matches[1],
1173
-                    'attributes' => array(
1174
-                        'href' => $url,
1175
-                    ),
1176
-                ),
1177
-            );
1178
-        }
1179
-    }
1180
-
1181
-    protected function inlineEmphasis($Excerpt)
1182
-    {
1183
-        if ( ! isset($Excerpt['text'][1]))
1184
-        {
1185
-            return;
1186
-        }
1187
-
1188
-        $marker = $Excerpt['text'][0];
1189
-
1190
-        if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))
1191
-        {
1192
-            $emphasis = 'strong';
1193
-        }
1194
-        elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))
1195
-        {
1196
-            $emphasis = 'em';
1197
-        }
1198
-        else
1199
-        {
1200
-            return;
1201
-        }
1202
-
1203
-        return array(
1204
-            'extent' => strlen($matches[0]),
1205
-            'element' => array(
1206
-                'name' => $emphasis,
1207
-                'handler' => 'line',
1208
-                'text' => $matches[1],
1209
-            ),
1210
-        );
1211
-    }
1212
-
1213
-    protected function inlineEscapeSequence($Excerpt)
1214
-    {
1215
-        if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
1216
-        {
1217
-            return array(
1218
-                'markup' => $Excerpt['text'][1],
1219
-                'extent' => 2,
1220
-            );
1221
-        }
1222
-    }
1223
-
1224
-    protected function inlineImage($Excerpt)
1225
-    {
1226
-        if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')
1227
-        {
1228
-            return;
1229
-        }
1230
-
1231
-        $Excerpt['text']= substr($Excerpt['text'], 1);
1232
-
1233
-        $Link = $this->inlineLink($Excerpt);
1234
-
1235
-        if ($Link === null)
1236
-        {
1237
-            return;
1238
-        }
1239
-
1240
-        $Inline = array(
1241
-            'extent' => $Link['extent'] + 1,
1242
-            'element' => array(
1243
-                'name' => 'img',
1244
-                'attributes' => array(
1245
-                    'src' => $Link['element']['attributes']['href'],
1246
-                    'alt' => $Link['element']['text'],
1247
-                ),
1248
-            ),
1249
-        );
1250
-
1251
-        $Inline['element']['attributes'] += $Link['element']['attributes'];
1252
-
1253
-        unset($Inline['element']['attributes']['href']);
1254
-
1255
-        return $Inline;
1256
-    }
1257
-
1258
-    protected function inlineLink($Excerpt)
1259
-    {
1260
-        $Element = array(
1261
-            'name' => 'a',
1262
-            'handler' => 'line',
1263
-            'nonNestables' => array('Url', 'Link'),
1264
-            'text' => null,
1265
-            'attributes' => array(
1266
-                'href' => null,
1267
-                'title' => null,
1268
-            ),
1269
-        );
1270
-
1271
-        $extent = 0;
1272
-
1273
-        $remainder = $Excerpt['text'];
1274
-
1275
-        if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
1276
-        {
1277
-            $Element['text'] = $matches[1];
1278
-
1279
-            $extent += strlen($matches[0]);
1280
-
1281
-            $remainder = substr($remainder, $extent);
1282
-        }
1283
-        else
1284
-        {
1285
-            return;
1286
-        }
1287
-
1288
-        if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches))
1289
-        {
1290
-            $Element['attributes']['href'] = $matches[1];
1291
-
1292
-            if (isset($matches[2]))
1293
-            {
1294
-                $Element['attributes']['title'] = substr($matches[2], 1, - 1);
1295
-            }
1296
-
1297
-            $extent += strlen($matches[0]);
1298
-        }
1299
-        else
1300
-        {
1301
-            if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
1302
-            {
1303
-                $definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
1304
-                $definition = strtolower($definition);
1305
-
1306
-                $extent += strlen($matches[0]);
1307
-            }
1308
-            else
1309
-            {
1310
-                $definition = strtolower($Element['text']);
1311
-            }
1312
-
1313
-            if ( ! isset($this->DefinitionData['Reference'][$definition]))
1314
-            {
1315
-                return;
1316
-            }
1317
-
1318
-            $Definition = $this->DefinitionData['Reference'][$definition];
1319
-
1320
-            $Element['attributes']['href'] = $Definition['url'];
1321
-            $Element['attributes']['title'] = $Definition['title'];
1322
-        }
1323
-
1324
-        return array(
1325
-            'extent' => $extent,
1326
-            'element' => $Element,
1327
-        );
1328
-    }
1329
-
1330
-    protected function inlineMarkup($Excerpt)
1331
-    {
1332
-        if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false)
1333
-        {
1334
-            return;
1335
-        }
1336
-
1337
-        if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*[ ]*>/s', $Excerpt['text'], $matches))
1338
-        {
1339
-            return array(
1340
-                'markup' => $matches[0],
1341
-                'extent' => strlen($matches[0]),
1342
-            );
1343
-        }
1344
-
1345
-        if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches))
1346
-        {
1347
-            return array(
1348
-                'markup' => $matches[0],
1349
-                'extent' => strlen($matches[0]),
1350
-            );
1351
-        }
1352
-
1353
-        if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
1354
-        {
1355
-            return array(
1356
-                'markup' => $matches[0],
1357
-                'extent' => strlen($matches[0]),
1358
-            );
1359
-        }
1360
-    }
1361
-
1362
-    protected function inlineSpecialCharacter($Excerpt)
1363
-    {
1364
-        if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text']))
1365
-        {
1366
-            return array(
1367
-                'markup' => '&amp;',
1368
-                'extent' => 1,
1369
-            );
1370
-        }
1371
-
1372
-        $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
1373
-
1374
-        if (isset($SpecialCharacter[$Excerpt['text'][0]]))
1375
-        {
1376
-            return array(
1377
-                'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
1378
-                'extent' => 1,
1379
-            );
1380
-        }
1381
-    }
1382
-
1383
-    protected function inlineStrikethrough($Excerpt)
1384
-    {
1385
-        if ( ! isset($Excerpt['text'][1]))
1386
-        {
1387
-            return;
1388
-        }
1389
-
1390
-        if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches))
1391
-        {
1392
-            return array(
1393
-                'extent' => strlen($matches[0]),
1394
-                'element' => array(
1395
-                    'name' => 'del',
1396
-                    'text' => $matches[1],
1397
-                    'handler' => 'line',
1398
-                ),
1399
-            );
1400
-        }
1401
-    }
1402
-
1403
-    protected function inlineUrl($Excerpt)
1404
-    {
1405
-        if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')
1406
-        {
1407
-            return;
1408
-        }
1409
-
1410
-        if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
1411
-        {
1412
-            $url = $matches[0][0];
1413
-
1414
-            $Inline = array(
1415
-                'extent' => strlen($matches[0][0]),
1416
-                'position' => $matches[0][1],
1417
-                'element' => array(
1418
-                    'name' => 'a',
1419
-                    'text' => $url,
1420
-                    'attributes' => array(
1421
-                        'href' => $url,
1422
-                    ),
1423
-                ),
1424
-            );
1425
-
1426
-            return $Inline;
1427
-        }
1428
-    }
1429
-
1430
-    protected function inlineUrlTag($Excerpt)
1431
-    {
1432
-        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
1433
-        {
1434
-            $url = $matches[1];
1435
-
1436
-            return array(
1437
-                'extent' => strlen($matches[0]),
1438
-                'element' => array(
1439
-                    'name' => 'a',
1440
-                    'text' => $url,
1441
-                    'attributes' => array(
1442
-                        'href' => $url,
1443
-                    ),
1444
-                ),
1445
-            );
1446
-        }
1447
-    }
1448
-
1449
-    # ~
1450
-
1451
-    protected function unmarkedText($text)
1452
-    {
1453
-        if ($this->breaksEnabled)
1454
-        {
1455
-            $text = preg_replace('/[ ]*\n/', "<br />\n", $text);
1456
-        }
1457
-        else
1458
-        {
1459
-            $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "<br />\n", $text);
1460
-            $text = str_replace(" \n", "\n", $text);
1461
-        }
1462
-
1463
-        return $text;
1464
-    }
1465
-
1466
-    #
1467
-    # Handlers
1468
-    #
1469
-
1470
-    protected function element(array $Element)
1471
-    {
1472
-        if ($this->safeMode)
1473
-        {
1474
-            $Element = $this->sanitiseElement($Element);
1475
-        }
1476
-
1477
-        $markup = '<'.$Element['name'];
1478
-
1479
-        if (isset($Element['attributes']))
1480
-        {
1481
-            foreach ($Element['attributes'] as $name => $value)
1482
-            {
1483
-                if ($value === null)
1484
-                {
1485
-                    continue;
1486
-                }
1487
-
1488
-                $markup .= ' '.$name.'="'.self::escape($value).'"';
1489
-            }
1490
-        }
1491
-
1492
-        $permitRawHtml = false;
1493
-
1494
-        if (isset($Element['text']))
1495
-        {
1496
-            $text = $Element['text'];
1497
-        }
1498
-        // very strongly consider an alternative if you're writing an
1499
-        // extension
1500
-        elseif (isset($Element['rawHtml']))
1501
-        {
1502
-            $text = $Element['rawHtml'];
1503
-            $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode'];
1504
-            $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
1505
-        }
1506
-
1507
-        if (isset($text))
1508
-        {
1509
-            $markup .= '>';
1510
-
1511
-            if (!isset($Element['nonNestables']))
1512
-            {
1513
-                $Element['nonNestables'] = array();
1514
-            }
1515
-
1516
-            if (isset($Element['handler']))
1517
-            {
1518
-                $markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
1519
-            }
1520
-            elseif (!$permitRawHtml)
1521
-            {
1522
-                $markup .= self::escape($text, true);
1523
-            }
1524
-            else
1525
-            {
1526
-                $markup .= $text;
1527
-            }
1528
-
1529
-            $markup .= '</'.$Element['name'].'>';
1530
-        }
1531
-        else
1532
-        {
1533
-            $markup .= ' />';
1534
-        }
1535
-
1536
-        return $markup;
1537
-    }
1538
-
1539
-    protected function elements(array $Elements)
1540
-    {
1541
-        $markup = '';
1542
-
1543
-        foreach ($Elements as $Element)
1544
-        {
1545
-            $markup .= "\n" . $this->element($Element);
1546
-        }
1547
-
1548
-        $markup .= "\n";
1549
-
1550
-        return $markup;
1551
-    }
1552
-
1553
-    # ~
1554
-
1555
-    protected function li($lines)
1556
-    {
1557
-        $markup = $this->lines($lines);
1558
-
1559
-        $trimmedMarkup = trim($markup);
1560
-
1561
-        if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>')
1562
-        {
1563
-            $markup = $trimmedMarkup;
1564
-            $markup = substr($markup, 3);
1565
-
1566
-            $position = strpos($markup, "</p>");
1567
-
1568
-            $markup = substr_replace($markup, '', $position, 4);
1569
-        }
1570
-
1571
-        return $markup;
1572
-    }
1573
-
1574
-    #
1575
-    # Deprecated Methods
1576
-    #
1577
-
1578
-    function parse($text)
1579
-    {
1580
-        $markup = $this->text($text);
1581
-
1582
-        return $markup;
1583
-    }
1584
-
1585
-    protected function sanitiseElement(array $Element)
1586
-    {
1587
-        static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';
1588
-        static $safeUrlNameToAtt  = array(
1589
-            'a'   => 'href',
1590
-            'img' => 'src',
1591
-        );
1592
-
1593
-        if (isset($safeUrlNameToAtt[$Element['name']]))
1594
-        {
1595
-            $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
1596
-        }
1597
-
1598
-        if ( ! empty($Element['attributes']))
1599
-        {
1600
-            foreach ($Element['attributes'] as $att => $val)
1601
-            {
1602
-                # filter out badly parsed attribute
1603
-                if ( ! preg_match($goodAttribute, $att))
1604
-                {
1605
-                    unset($Element['attributes'][$att]);
1606
-                }
1607
-                # dump onevent attribute
1608
-                elseif (self::striAtStart($att, 'on'))
1609
-                {
1610
-                    unset($Element['attributes'][$att]);
1611
-                }
1612
-            }
1613
-        }
1614
-
1615
-        return $Element;
1616
-    }
1617
-
1618
-    protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
1619
-    {
1620
-        foreach ($this->safeLinksWhitelist as $scheme)
1621
-        {
1622
-            if (self::striAtStart($Element['attributes'][$attribute], $scheme))
1623
-            {
1624
-                return $Element;
1625
-            }
1626
-        }
1627
-
1628
-        $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);
1629
-
1630
-        return $Element;
1631
-    }
1632
-
1633
-    #
1634
-    # Static Methods
1635
-    #
1636
-
1637
-    protected static function escape($text, $allowQuotes = false)
1638
-    {
1639
-        return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
1640
-    }
1641
-
1642
-    protected static function striAtStart($string, $needle)
1643
-    {
1644
-        $len = strlen($needle);
1645
-
1646
-        if ($len > strlen($string))
1647
-        {
1648
-            return false;
1649
-        }
1650
-        else
1651
-        {
1652
-            return strtolower(substr($string, 0, $len)) === strtolower($needle);
1653
-        }
1654
-    }
1655
-
1656
-    static function instance($name = 'default')
1657
-    {
1658
-        if (isset(self::$instances[$name]))
1659
-        {
1660
-            return self::$instances[$name];
1661
-        }
1662
-
1663
-        $instance = new static();
1664
-
1665
-        self::$instances[$name] = $instance;
1666
-
1667
-        return $instance;
1668
-    }
1669
-
1670
-    private static $instances = array();
1671
-
1672
-    #
1673
-    # Fields
1674
-    #
1675
-
1676
-    protected $DefinitionData;
1677
-
1678
-    #
1679
-    # Read-Only
1680
-
1681
-    protected $specialCharacters = array(
1682
-        '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',
1683
-    );
1684
-
1685
-    protected $StrongRegex = array(
1686
-        '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
1687
-        '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',
1688
-    );
1689
-
1690
-    protected $EmRegex = array(
1691
-        '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
1692
-        '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us',
1693
-    );
1694
-
1695
-    protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?';
1696
-
1697
-    protected $voidElements = array(
1698
-        'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',
1699
-    );
1700
-
1701
-    protected $textLevelElements = array(
1702
-        'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
1703
-        'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
1704
-        'i', 'rp', 'del', 'code',          'strike', 'marquee',
1705
-        'q', 'rt', 'ins', 'font',          'strong',
1706
-        's', 'tt', 'kbd', 'mark',
1707
-        'u', 'xm', 'sub', 'nobr',
1708
-                   'sup', 'ruby',
1709
-                   'var', 'span',
1710
-                   'wbr', 'time',
1711
-    );
1072
+				if ( ! empty($nonNestables) and in_array($inlineType, $nonNestables))
1073
+				{
1074
+					continue;
1075
+				}
1076
+
1077
+				$Inline = $this->{'inline'.$inlineType}($Excerpt);
1078
+
1079
+				if ( ! isset($Inline))
1080
+				{
1081
+					continue;
1082
+				}
1083
+
1084
+				# makes sure that the inline belongs to "our" marker
1085
+
1086
+				if (isset($Inline['position']) and $Inline['position'] > $markerPosition)
1087
+				{
1088
+					continue;
1089
+				}
1090
+
1091
+				# sets a default inline position
1092
+
1093
+				if ( ! isset($Inline['position']))
1094
+				{
1095
+					$Inline['position'] = $markerPosition;
1096
+				}
1097
+
1098
+				# cause the new element to 'inherit' our non nestables
1099
+
1100
+				foreach ($nonNestables as $non_nestable)
1101
+				{
1102
+					$Inline['element']['nonNestables'][] = $non_nestable;
1103
+				}
1104
+
1105
+				# the text that comes before the inline
1106
+				$unmarkedText = substr($text, 0, $Inline['position']);
1107
+
1108
+				# compile the unmarked text
1109
+				$markup .= $this->unmarkedText($unmarkedText);
1110
+
1111
+				# compile the inline
1112
+				$markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
1113
+
1114
+				# remove the examined text
1115
+				$text = substr($text, $Inline['position'] + $Inline['extent']);
1116
+
1117
+				continue 2;
1118
+			}
1119
+
1120
+			# the marker does not belong to an inline
1121
+
1122
+			$unmarkedText = substr($text, 0, $markerPosition + 1);
1123
+
1124
+			$markup .= $this->unmarkedText($unmarkedText);
1125
+
1126
+			$text = substr($text, $markerPosition + 1);
1127
+		}
1128
+
1129
+		$markup .= $this->unmarkedText($text);
1130
+
1131
+		return $markup;
1132
+	}
1133
+
1134
+	#
1135
+	# ~
1136
+	#
1137
+
1138
+	protected function inlineCode($Excerpt)
1139
+	{
1140
+		$marker = $Excerpt['text'][0];
1141
+
1142
+		if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
1143
+		{
1144
+			$text = $matches[2];
1145
+			$text = preg_replace("/[ ]*\n/", ' ', $text);
1146
+
1147
+			return array(
1148
+				'extent' => strlen($matches[0]),
1149
+				'element' => array(
1150
+					'name' => 'code',
1151
+					'text' => $text,
1152
+				),
1153
+			);
1154
+		}
1155
+	}
1156
+
1157
+	protected function inlineEmailTag($Excerpt)
1158
+	{
1159
+		if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
1160
+		{
1161
+			$url = $matches[1];
1162
+
1163
+			if ( ! isset($matches[2]))
1164
+			{
1165
+				$url = 'mailto:' . $url;
1166
+			}
1167
+
1168
+			return array(
1169
+				'extent' => strlen($matches[0]),
1170
+				'element' => array(
1171
+					'name' => 'a',
1172
+					'text' => $matches[1],
1173
+					'attributes' => array(
1174
+						'href' => $url,
1175
+					),
1176
+				),
1177
+			);
1178
+		}
1179
+	}
1180
+
1181
+	protected function inlineEmphasis($Excerpt)
1182
+	{
1183
+		if ( ! isset($Excerpt['text'][1]))
1184
+		{
1185
+			return;
1186
+		}
1187
+
1188
+		$marker = $Excerpt['text'][0];
1189
+
1190
+		if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))
1191
+		{
1192
+			$emphasis = 'strong';
1193
+		}
1194
+		elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))
1195
+		{
1196
+			$emphasis = 'em';
1197
+		}
1198
+		else
1199
+		{
1200
+			return;
1201
+		}
1202
+
1203
+		return array(
1204
+			'extent' => strlen($matches[0]),
1205
+			'element' => array(
1206
+				'name' => $emphasis,
1207
+				'handler' => 'line',
1208
+				'text' => $matches[1],
1209
+			),
1210
+		);
1211
+	}
1212
+
1213
+	protected function inlineEscapeSequence($Excerpt)
1214
+	{
1215
+		if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
1216
+		{
1217
+			return array(
1218
+				'markup' => $Excerpt['text'][1],
1219
+				'extent' => 2,
1220
+			);
1221
+		}
1222
+	}
1223
+
1224
+	protected function inlineImage($Excerpt)
1225
+	{
1226
+		if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')
1227
+		{
1228
+			return;
1229
+		}
1230
+
1231
+		$Excerpt['text']= substr($Excerpt['text'], 1);
1232
+
1233
+		$Link = $this->inlineLink($Excerpt);
1234
+
1235
+		if ($Link === null)
1236
+		{
1237
+			return;
1238
+		}
1239
+
1240
+		$Inline = array(
1241
+			'extent' => $Link['extent'] + 1,
1242
+			'element' => array(
1243
+				'name' => 'img',
1244
+				'attributes' => array(
1245
+					'src' => $Link['element']['attributes']['href'],
1246
+					'alt' => $Link['element']['text'],
1247
+				),
1248
+			),
1249
+		);
1250
+
1251
+		$Inline['element']['attributes'] += $Link['element']['attributes'];
1252
+
1253
+		unset($Inline['element']['attributes']['href']);
1254
+
1255
+		return $Inline;
1256
+	}
1257
+
1258
+	protected function inlineLink($Excerpt)
1259
+	{
1260
+		$Element = array(
1261
+			'name' => 'a',
1262
+			'handler' => 'line',
1263
+			'nonNestables' => array('Url', 'Link'),
1264
+			'text' => null,
1265
+			'attributes' => array(
1266
+				'href' => null,
1267
+				'title' => null,
1268
+			),
1269
+		);
1270
+
1271
+		$extent = 0;
1272
+
1273
+		$remainder = $Excerpt['text'];
1274
+
1275
+		if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
1276
+		{
1277
+			$Element['text'] = $matches[1];
1278
+
1279
+			$extent += strlen($matches[0]);
1280
+
1281
+			$remainder = substr($remainder, $extent);
1282
+		}
1283
+		else
1284
+		{
1285
+			return;
1286
+		}
1287
+
1288
+		if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches))
1289
+		{
1290
+			$Element['attributes']['href'] = $matches[1];
1291
+
1292
+			if (isset($matches[2]))
1293
+			{
1294
+				$Element['attributes']['title'] = substr($matches[2], 1, - 1);
1295
+			}
1296
+
1297
+			$extent += strlen($matches[0]);
1298
+		}
1299
+		else
1300
+		{
1301
+			if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
1302
+			{
1303
+				$definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
1304
+				$definition = strtolower($definition);
1305
+
1306
+				$extent += strlen($matches[0]);
1307
+			}
1308
+			else
1309
+			{
1310
+				$definition = strtolower($Element['text']);
1311
+			}
1312
+
1313
+			if ( ! isset($this->DefinitionData['Reference'][$definition]))
1314
+			{
1315
+				return;
1316
+			}
1317
+
1318
+			$Definition = $this->DefinitionData['Reference'][$definition];
1319
+
1320
+			$Element['attributes']['href'] = $Definition['url'];
1321
+			$Element['attributes']['title'] = $Definition['title'];
1322
+		}
1323
+
1324
+		return array(
1325
+			'extent' => $extent,
1326
+			'element' => $Element,
1327
+		);
1328
+	}
1329
+
1330
+	protected function inlineMarkup($Excerpt)
1331
+	{
1332
+		if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false)
1333
+		{
1334
+			return;
1335
+		}
1336
+
1337
+		if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*[ ]*>/s', $Excerpt['text'], $matches))
1338
+		{
1339
+			return array(
1340
+				'markup' => $matches[0],
1341
+				'extent' => strlen($matches[0]),
1342
+			);
1343
+		}
1344
+
1345
+		if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches))
1346
+		{
1347
+			return array(
1348
+				'markup' => $matches[0],
1349
+				'extent' => strlen($matches[0]),
1350
+			);
1351
+		}
1352
+
1353
+		if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
1354
+		{
1355
+			return array(
1356
+				'markup' => $matches[0],
1357
+				'extent' => strlen($matches[0]),
1358
+			);
1359
+		}
1360
+	}
1361
+
1362
+	protected function inlineSpecialCharacter($Excerpt)
1363
+	{
1364
+		if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text']))
1365
+		{
1366
+			return array(
1367
+				'markup' => '&amp;',
1368
+				'extent' => 1,
1369
+			);
1370
+		}
1371
+
1372
+		$SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
1373
+
1374
+		if (isset($SpecialCharacter[$Excerpt['text'][0]]))
1375
+		{
1376
+			return array(
1377
+				'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
1378
+				'extent' => 1,
1379
+			);
1380
+		}
1381
+	}
1382
+
1383
+	protected function inlineStrikethrough($Excerpt)
1384
+	{
1385
+		if ( ! isset($Excerpt['text'][1]))
1386
+		{
1387
+			return;
1388
+		}
1389
+
1390
+		if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches))
1391
+		{
1392
+			return array(
1393
+				'extent' => strlen($matches[0]),
1394
+				'element' => array(
1395
+					'name' => 'del',
1396
+					'text' => $matches[1],
1397
+					'handler' => 'line',
1398
+				),
1399
+			);
1400
+		}
1401
+	}
1402
+
1403
+	protected function inlineUrl($Excerpt)
1404
+	{
1405
+		if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')
1406
+		{
1407
+			return;
1408
+		}
1409
+
1410
+		if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
1411
+		{
1412
+			$url = $matches[0][0];
1413
+
1414
+			$Inline = array(
1415
+				'extent' => strlen($matches[0][0]),
1416
+				'position' => $matches[0][1],
1417
+				'element' => array(
1418
+					'name' => 'a',
1419
+					'text' => $url,
1420
+					'attributes' => array(
1421
+						'href' => $url,
1422
+					),
1423
+				),
1424
+			);
1425
+
1426
+			return $Inline;
1427
+		}
1428
+	}
1429
+
1430
+	protected function inlineUrlTag($Excerpt)
1431
+	{
1432
+		if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
1433
+		{
1434
+			$url = $matches[1];
1435
+
1436
+			return array(
1437
+				'extent' => strlen($matches[0]),
1438
+				'element' => array(
1439
+					'name' => 'a',
1440
+					'text' => $url,
1441
+					'attributes' => array(
1442
+						'href' => $url,
1443
+					),
1444
+				),
1445
+			);
1446
+		}
1447
+	}
1448
+
1449
+	# ~
1450
+
1451
+	protected function unmarkedText($text)
1452
+	{
1453
+		if ($this->breaksEnabled)
1454
+		{
1455
+			$text = preg_replace('/[ ]*\n/', "<br />\n", $text);
1456
+		}
1457
+		else
1458
+		{
1459
+			$text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "<br />\n", $text);
1460
+			$text = str_replace(" \n", "\n", $text);
1461
+		}
1462
+
1463
+		return $text;
1464
+	}
1465
+
1466
+	#
1467
+	# Handlers
1468
+	#
1469
+
1470
+	protected function element(array $Element)
1471
+	{
1472
+		if ($this->safeMode)
1473
+		{
1474
+			$Element = $this->sanitiseElement($Element);
1475
+		}
1476
+
1477
+		$markup = '<'.$Element['name'];
1478
+
1479
+		if (isset($Element['attributes']))
1480
+		{
1481
+			foreach ($Element['attributes'] as $name => $value)
1482
+			{
1483
+				if ($value === null)
1484
+				{
1485
+					continue;
1486
+				}
1487
+
1488
+				$markup .= ' '.$name.'="'.self::escape($value).'"';
1489
+			}
1490
+		}
1491
+
1492
+		$permitRawHtml = false;
1493
+
1494
+		if (isset($Element['text']))
1495
+		{
1496
+			$text = $Element['text'];
1497
+		}
1498
+		// very strongly consider an alternative if you're writing an
1499
+		// extension
1500
+		elseif (isset($Element['rawHtml']))
1501
+		{
1502
+			$text = $Element['rawHtml'];
1503
+			$allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode'];
1504
+			$permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
1505
+		}
1506
+
1507
+		if (isset($text))
1508
+		{
1509
+			$markup .= '>';
1510
+
1511
+			if (!isset($Element['nonNestables']))
1512
+			{
1513
+				$Element['nonNestables'] = array();
1514
+			}
1515
+
1516
+			if (isset($Element['handler']))
1517
+			{
1518
+				$markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
1519
+			}
1520
+			elseif (!$permitRawHtml)
1521
+			{
1522
+				$markup .= self::escape($text, true);
1523
+			}
1524
+			else
1525
+			{
1526
+				$markup .= $text;
1527
+			}
1528
+
1529
+			$markup .= '</'.$Element['name'].'>';
1530
+		}
1531
+		else
1532
+		{
1533
+			$markup .= ' />';
1534
+		}
1535
+
1536
+		return $markup;
1537
+	}
1538
+
1539
+	protected function elements(array $Elements)
1540
+	{
1541
+		$markup = '';
1542
+
1543
+		foreach ($Elements as $Element)
1544
+		{
1545
+			$markup .= "\n" . $this->element($Element);
1546
+		}
1547
+
1548
+		$markup .= "\n";
1549
+
1550
+		return $markup;
1551
+	}
1552
+
1553
+	# ~
1554
+
1555
+	protected function li($lines)
1556
+	{
1557
+		$markup = $this->lines($lines);
1558
+
1559
+		$trimmedMarkup = trim($markup);
1560
+
1561
+		if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>')
1562
+		{
1563
+			$markup = $trimmedMarkup;
1564
+			$markup = substr($markup, 3);
1565
+
1566
+			$position = strpos($markup, "</p>");
1567
+
1568
+			$markup = substr_replace($markup, '', $position, 4);
1569
+		}
1570
+
1571
+		return $markup;
1572
+	}
1573
+
1574
+	#
1575
+	# Deprecated Methods
1576
+	#
1577
+
1578
+	function parse($text)
1579
+	{
1580
+		$markup = $this->text($text);
1581
+
1582
+		return $markup;
1583
+	}
1584
+
1585
+	protected function sanitiseElement(array $Element)
1586
+	{
1587
+		static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';
1588
+		static $safeUrlNameToAtt  = array(
1589
+			'a'   => 'href',
1590
+			'img' => 'src',
1591
+		);
1592
+
1593
+		if (isset($safeUrlNameToAtt[$Element['name']]))
1594
+		{
1595
+			$Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
1596
+		}
1597
+
1598
+		if ( ! empty($Element['attributes']))
1599
+		{
1600
+			foreach ($Element['attributes'] as $att => $val)
1601
+			{
1602
+				# filter out badly parsed attribute
1603
+				if ( ! preg_match($goodAttribute, $att))
1604
+				{
1605
+					unset($Element['attributes'][$att]);
1606
+				}
1607
+				# dump onevent attribute
1608
+				elseif (self::striAtStart($att, 'on'))
1609
+				{
1610
+					unset($Element['attributes'][$att]);
1611
+				}
1612
+			}
1613
+		}
1614
+
1615
+		return $Element;
1616
+	}
1617
+
1618
+	protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
1619
+	{
1620
+		foreach ($this->safeLinksWhitelist as $scheme)
1621
+		{
1622
+			if (self::striAtStart($Element['attributes'][$attribute], $scheme))
1623
+			{
1624
+				return $Element;
1625
+			}
1626
+		}
1627
+
1628
+		$Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);
1629
+
1630
+		return $Element;
1631
+	}
1632
+
1633
+	#
1634
+	# Static Methods
1635
+	#
1636
+
1637
+	protected static function escape($text, $allowQuotes = false)
1638
+	{
1639
+		return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
1640
+	}
1641
+
1642
+	protected static function striAtStart($string, $needle)
1643
+	{
1644
+		$len = strlen($needle);
1645
+
1646
+		if ($len > strlen($string))
1647
+		{
1648
+			return false;
1649
+		}
1650
+		else
1651
+		{
1652
+			return strtolower(substr($string, 0, $len)) === strtolower($needle);
1653
+		}
1654
+	}
1655
+
1656
+	static function instance($name = 'default')
1657
+	{
1658
+		if (isset(self::$instances[$name]))
1659
+		{
1660
+			return self::$instances[$name];
1661
+		}
1662
+
1663
+		$instance = new static();
1664
+
1665
+		self::$instances[$name] = $instance;
1666
+
1667
+		return $instance;
1668
+	}
1669
+
1670
+	private static $instances = array();
1671
+
1672
+	#
1673
+	# Fields
1674
+	#
1675
+
1676
+	protected $DefinitionData;
1677
+
1678
+	#
1679
+	# Read-Only
1680
+
1681
+	protected $specialCharacters = array(
1682
+		'\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',
1683
+	);
1684
+
1685
+	protected $StrongRegex = array(
1686
+		'*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',
1687
+		'_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',
1688
+	);
1689
+
1690
+	protected $EmRegex = array(
1691
+		'*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
1692
+		'_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us',
1693
+	);
1694
+
1695
+	protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?';
1696
+
1697
+	protected $voidElements = array(
1698
+		'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',
1699
+	);
1700
+
1701
+	protected $textLevelElements = array(
1702
+		'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
1703
+		'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
1704
+		'i', 'rp', 'del', 'code',          'strike', 'marquee',
1705
+		'q', 'rt', 'ins', 'font',          'strong',
1706
+		's', 'tt', 'kbd', 'mark',
1707
+		'u', 'xm', 'sub', 'nobr',
1708
+				   'sup', 'ruby',
1709
+				   'var', 'span',
1710
+				   'wbr', 'time',
1711
+	);
1712 1712
 }
Please login to merge, or discard this patch.
htdocs/includes/nusoap/lib/Mail/mimePart.php 1 patch
Indentation   +1171 added lines, -1171 removed lines patch added patch discarded remove patch
@@ -75,520 +75,520 @@  discard block
 block discarded – undo
75 75
  */
76 76
 class Mail_mimePart
77 77
 {
78
-    /**
79
-    * The encoding type of this part
80
-    *
81
-    * @var string
82
-    * @access private
83
-    */
84
-    var $_encoding;
85
-
86
-    /**
87
-    * An array of subparts
88
-    *
89
-    * @var array
90
-    * @access private
91
-    */
92
-    var $_subparts;
93
-
94
-    /**
95
-    * The output of this part after being built
96
-    *
97
-    * @var string
98
-    * @access private
99
-    */
100
-    var $_encoded;
101
-
102
-    /**
103
-    * Headers for this part
104
-    *
105
-    * @var array
106
-    * @access private
107
-    */
108
-    var $_headers;
109
-
110
-    /**
111
-    * The body of this part (not encoded)
112
-    *
113
-    * @var string
114
-    * @access private
115
-    */
116
-    var $_body;
117
-
118
-    /**
119
-    * The location of file with body of this part (not encoded)
120
-    *
121
-    * @var string
122
-    * @access private
123
-    */
124
-    var $_body_file;
125
-
126
-    /**
127
-    * The end-of-line sequence
128
-    *
129
-    * @var string
130
-    * @access private
131
-    */
132
-    var $_eol = "\r\n";
133
-
134
-
135
-    /**
136
-    * Constructor.
137
-    *
138
-    * Sets up the object.
139
-    *
140
-    * @param string $body   The body of the mime part if any.
141
-    * @param array  $params An associative array of optional parameters:
142
-    *     content_type      - The content type for this part eg multipart/mixed
143
-    *     encoding          - The encoding to use, 7bit, 8bit,
144
-    *                         base64, or quoted-printable
145
-    *     charset           - Content character set
146
-    *     cid               - Content ID to apply
147
-    *     disposition       - Content disposition, inline or attachment
148
-    *     filename          - Filename parameter for content disposition
149
-    *     description       - Content description
150
-    *     name_encoding     - Encoding of the attachment name (Content-Type)
151
-    *                         By default filenames are encoded using RFC2231
152
-    *                         Here you can set RFC2047 encoding (quoted-printable
153
-    *                         or base64) instead
154
-    *     filename_encoding - Encoding of the attachment filename (Content-Disposition)
155
-    *                         See 'name_encoding'
156
-    *     headers_charset   - Charset of the headers e.g. filename, description.
157
-    *                         If not set, 'charset' will be used
158
-    *     eol               - End of line sequence. Default: "\r\n"
159
-    *     headers           - Hash array with additional part headers. Array keys can be
160
-    *                         in form of <header_name>:<parameter_name>
161
-    *     body_file         - Location of file with part's body (instead of $body)
162
-    *
163
-    * @access public
164
-    */
165
-    function Mail_mimePart($body = '', $params = array())
166
-    {
167
-        if (!empty($params['eol'])) {
168
-            $this->_eol = $params['eol'];
169
-        } else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat.
170
-            $this->_eol = MAIL_MIMEPART_CRLF;
171
-        }
172
-
173
-        // Additional part headers
174
-        if (!empty($params['headers']) && is_array($params['headers'])) {
175
-            $headers = $params['headers'];
176
-        }
177
-
178
-        foreach ($params as $key => $value) {
179
-            switch ($key) {
180
-            case 'encoding':
181
-                $this->_encoding = $value;
182
-                $headers['Content-Transfer-Encoding'] = $value;
183
-                break;
184
-
185
-            case 'cid':
186
-                $headers['Content-ID'] = '<' . $value . '>';
187
-                break;
188
-
189
-            case 'location':
190
-                $headers['Content-Location'] = $value;
191
-                break;
192
-
193
-            case 'body_file':
194
-                $this->_body_file = $value;
195
-                break;
196
-
197
-            // for backward compatibility
198
-            case 'dfilename':
199
-                $params['filename'] = $value;
200
-                break;
201
-            }
202
-        }
203
-
204
-        // Default content-type
205
-        if (empty($params['content_type'])) {
206
-            $params['content_type'] = 'text/plain';
207
-        }
208
-
209
-        // Content-Type
210
-        $headers['Content-Type'] = $params['content_type'];
211
-        if (!empty($params['charset'])) {
212
-            $charset = "charset={$params['charset']}";
213
-            // place charset parameter in the same line, if possible
214
-            if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) {
215
-                $headers['Content-Type'] .= '; ';
216
-            } else {
217
-                $headers['Content-Type'] .= ';' . $this->_eol . ' ';
218
-            }
219
-            $headers['Content-Type'] .= $charset;
220
-
221
-            // Default headers charset
222
-            if (!isset($params['headers_charset'])) {
223
-                $params['headers_charset'] = $params['charset'];
224
-            }
225
-        }
226
-
227
-        // header values encoding parameters
228
-        $h_charset  = !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII';
229
-        $h_language = !empty($params['language']) ? $params['language'] : null;
230
-        $h_encoding = !empty($params['name_encoding']) ? $params['name_encoding'] : null;
231
-
232
-
233
-        if (!empty($params['filename'])) {
234
-            $headers['Content-Type'] .= ';' . $this->_eol;
235
-            $headers['Content-Type'] .= $this->_buildHeaderParam(
236
-                'name', $params['filename'], $h_charset, $h_language, $h_encoding
237
-            );
238
-        }
239
-
240
-        // Content-Disposition
241
-        if (!empty($params['disposition'])) {
242
-            $headers['Content-Disposition'] = $params['disposition'];
243
-            if (!empty($params['filename'])) {
244
-                $headers['Content-Disposition'] .= ';' . $this->_eol;
245
-                $headers['Content-Disposition'] .= $this->_buildHeaderParam(
246
-                    'filename', $params['filename'], $h_charset, $h_language,
247
-                    !empty($params['filename_encoding']) ? $params['filename_encoding'] : null
248
-                );
249
-            }
250
-
251
-            // add attachment size
252
-            $size = $this->_body_file ? filesize($this->_body_file) : strlen($body);
253
-            if ($size) {
254
-                $headers['Content-Disposition'] .= ';' . $this->_eol . ' size=' . $size;
255
-            }
256
-        }
257
-
258
-        if (!empty($params['description'])) {
259
-            $headers['Content-Description'] = $this->encodeHeader(
260
-                'Content-Description', $params['description'], $h_charset, $h_encoding,
261
-                $this->_eol
262
-            );
263
-        }
264
-
265
-        // Search and add existing headers' parameters
266
-        foreach ($headers as $key => $value) {
267
-            $items = explode(':', $key);
268
-            if (count($items) == 2) {
269
-                $header = $items[0];
270
-                $param  = $items[1];
271
-                if (isset($headers[$header])) {
272
-                    $headers[$header] .= ';' . $this->_eol;
273
-                }
274
-                $headers[$header] .= $this->_buildHeaderParam(
275
-                    $param, $value, $h_charset, $h_language, $h_encoding
276
-                );
277
-                unset($headers[$key]);
278
-            }
279
-        }
280
-
281
-        // Default encoding
282
-        if (!isset($this->_encoding)) {
283
-            $this->_encoding = '7bit';
284
-        }
285
-
286
-        // Assign stuff to member variables
287
-        $this->_encoded  = array();
288
-        $this->_headers  = $headers;
289
-        $this->_body     = $body;
290
-    }
291
-
292
-    /**
293
-     * Encodes and returns the email. Also stores
294
-     * it in the encoded member variable
295
-     *
296
-     * @param string $boundary Pre-defined boundary string
297
-     *
298
-     * @return An associative array containing two elements,
299
-     *         body and headers. The headers element is itself
300
-     *         an indexed array. On error returns PEAR error object.
301
-     * @access public
302
-     */
303
-    function encode($boundary=null)
304
-    {
305
-        $encoded =& $this->_encoded;
306
-
307
-        if (count($this->_subparts)) {
308
-            $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
309
-            $eol = $this->_eol;
310
-
311
-            $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
312
-
313
-            $encoded['body'] = ''; 
314
-
315
-            for ($i = 0; $i < count($this->_subparts); $i++) {
316
-                $encoded['body'] .= '--' . $boundary . $eol;
317
-                $tmp = $this->_subparts[$i]->encode();
318
-                if ($this->_isError($tmp)) {
319
-                    return $tmp;
320
-                }
321
-                foreach ($tmp['headers'] as $key => $value) {
322
-                    $encoded['body'] .= $key . ': ' . $value . $eol;
323
-                }
324
-                $encoded['body'] .= $eol . $tmp['body'] . $eol;
325
-            }
326
-
327
-            $encoded['body'] .= '--' . $boundary . '--' . $eol;
328
-
329
-        } else if ($this->_body) {
330
-            $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding);
331
-        } else if ($this->_body_file) {
332
-            // Temporarily reset magic_quotes_runtime for file reads and writes
333
-            if ($magic_quote_setting = get_magic_quotes_runtime()) {
334
-                @ini_set('magic_quotes_runtime', 0);
335
-            }
336
-            $body = $this->_getEncodedDataFromFile($this->_body_file, $this->_encoding);
337
-            if ($magic_quote_setting) {
338
-                @ini_set('magic_quotes_runtime', $magic_quote_setting);
339
-            }
340
-
341
-            if ($this->_isError($body)) {
342
-                return $body;
343
-            }
344
-            $encoded['body'] = $body;
345
-        } else {
346
-            $encoded['body'] = '';
347
-        }
348
-
349
-        // Add headers to $encoded
350
-        $encoded['headers'] =& $this->_headers;
351
-
352
-        return $encoded;
353
-    }
354
-
355
-    /**
356
-     * Encodes and saves the email into file. File must exist.
357
-     * Data will be appended to the file.
358
-     *
359
-     * @param string  $filename  Output file location
360
-     * @param string  $boundary  Pre-defined boundary string
361
-     * @param boolean $skip_head True if you don't want to save headers
362
-     *
363
-     * @return array An associative array containing message headers
364
-     *               or PEAR error object
365
-     * @access public
366
-     * @since 1.6.0
367
-     */
368
-    function encodeToFile($filename, $boundary=null, $skip_head=false)
369
-    {
370
-        if (file_exists($filename) && !is_writable($filename)) {
371
-            $err = $this->_raiseError('File is not writeable: ' . $filename);
372
-            return $err;
373
-        }
374
-
375
-        if (!($fh = fopen($filename, 'ab'))) {
376
-            $err = $this->_raiseError('Unable to open file: ' . $filename);
377
-            return $err;
378
-        }
379
-
380
-        // Temporarily reset magic_quotes_runtime for file reads and writes
381
-        if ($magic_quote_setting = get_magic_quotes_runtime()) {
382
-            @ini_set('magic_quotes_runtime', 0);
383
-        }
384
-
385
-        $res = $this->_encodePartToFile($fh, $boundary, $skip_head);
386
-
387
-        fclose($fh);
388
-
389
-        if ($magic_quote_setting) {
390
-            @ini_set('magic_quotes_runtime', $magic_quote_setting);
391
-        }
392
-
393
-        return $this->_isError($res) ? $res : $this->_headers;
394
-    }
395
-
396
-    /**
397
-     * Encodes given email part into file
398
-     *
399
-     * @param string  $fh        Output file handle
400
-     * @param string  $boundary  Pre-defined boundary string
401
-     * @param boolean $skip_head True if you don't want to save headers
402
-     *
403
-     * @return array True on sucess or PEAR error object
404
-     * @access private
405
-     */
406
-    function _encodePartToFile($fh, $boundary=null, $skip_head=false)
407
-    {
408
-        $eol = $this->_eol;
409
-
410
-        if (count($this->_subparts)) {
411
-            $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
412
-            $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
413
-        }
414
-
415
-        if (!$skip_head) {
416
-            foreach ($this->_headers as $key => $value) {
417
-                fwrite($fh, $key . ': ' . $value . $eol);
418
-            }
419
-            $f_eol = $eol;
420
-        } else {
421
-            $f_eol = '';
422
-        }
423
-
424
-        if (count($this->_subparts)) {
425
-            for ($i = 0; $i < count($this->_subparts); $i++) {
426
-                fwrite($fh, $f_eol . '--' . $boundary . $eol);
427
-                $res = $this->_subparts[$i]->_encodePartToFile($fh);
428
-                if ($this->_isError($res)) {
429
-                    return $res;
430
-                }
431
-                $f_eol = $eol;
432
-            }
433
-
434
-            fwrite($fh, $eol . '--' . $boundary . '--' . $eol);
435
-
436
-        } else if ($this->_body) {
437
-            fwrite($fh, $f_eol . $this->_getEncodedData($this->_body, $this->_encoding));
438
-        } else if ($this->_body_file) {
439
-            fwrite($fh, $f_eol);
440
-            $res = $this->_getEncodedDataFromFile(
441
-                $this->_body_file, $this->_encoding, $fh
442
-            );
443
-            if ($this->_isError($res)) {
444
-                return $res;
445
-            }
446
-        }
447
-
448
-        return true;
449
-    }
450
-
451
-    /**
452
-     * Adds a subpart to current mime part and returns
453
-     * a reference to it
454
-     *
455
-     * @param string $body   The body of the subpart, if any.
456
-     * @param array  $params The parameters for the subpart, same
457
-     *                       as the $params argument for constructor.
458
-     *
459
-     * @return Mail_mimePart A reference to the part you just added. In PHP4, it is
460
-     *                       crucial if using multipart/* in your subparts that
461
-     *                       you use =& in your script when calling this function,
462
-     *                       otherwise you will not be able to add further subparts.
463
-     * @access public
464
-     */
465
-    function &addSubpart($body, $params)
466
-    {
467
-        $this->_subparts[] = $part = new Mail_mimePart($body, $params);
468
-        return $part;
469
-    }
470
-
471
-    /**
472
-     * Returns encoded data based upon encoding passed to it
473
-     *
474
-     * @param string $data     The data to encode.
475
-     * @param string $encoding The encoding type to use, 7bit, base64,
476
-     *                         or quoted-printable.
477
-     *
478
-     * @return string
479
-     * @access private
480
-     */
481
-    function _getEncodedData($data, $encoding)
482
-    {
483
-        switch ($encoding) {
484
-        case 'quoted-printable':
485
-            return $this->_quotedPrintableEncode($data);
486
-            break;
487
-
488
-        case 'base64':
489
-            return rtrim(chunk_split(base64_encode($data), 76, $this->_eol));
490
-            break;
491
-
492
-        case '8bit':
493
-        case '7bit':
494
-        default:
495
-            return $data;
496
-        }
497
-    }
498
-
499
-    /**
500
-     * Returns encoded data based upon encoding passed to it
501
-     *
502
-     * @param string   $filename Data file location
503
-     * @param string   $encoding The encoding type to use, 7bit, base64,
504
-     *                           or quoted-printable.
505
-     * @param resource $fh       Output file handle. If set, data will be
506
-     *                           stored into it instead of returning it
507
-     *
508
-     * @return string Encoded data or PEAR error object
509
-     * @access private
510
-     */
511
-    function _getEncodedDataFromFile($filename, $encoding, $fh=null)
512
-    {
513
-        if (!is_readable($filename)) {
514
-            $err = $this->_raiseError('Unable to read file: ' . $filename);
515
-            return $err;
516
-        }
517
-
518
-        if (!($fd = fopen($filename, 'rb'))) {
519
-            $err = $this->_raiseError('Could not open file: ' . $filename);
520
-            return $err;
521
-        }
522
-
523
-        $data = '';
524
-
525
-        switch ($encoding) {
526
-        case 'quoted-printable':
527
-            while (!feof($fd)) {
528
-                $buffer = $this->_quotedPrintableEncode(fgets($fd));
529
-                if ($fh) {
530
-                    fwrite($fh, $buffer);
531
-                } else {
532
-                    $data .= $buffer;
533
-                }
534
-            }
535
-            break;
536
-
537
-        case 'base64':
538
-            while (!feof($fd)) {
539
-                // Should read in a multiple of 57 bytes so that
540
-                // the output is 76 bytes per line. Don't use big chunks
541
-                // because base64 encoding is memory expensive
542
-                $buffer = fread($fd, 57 * 9198); // ca. 0.5 MB
543
-                $buffer = base64_encode($buffer);
544
-                $buffer = chunk_split($buffer, 76, $this->_eol);
545
-                if (feof($fd)) {
546
-                    $buffer = rtrim($buffer);
547
-                }
548
-
549
-                if ($fh) {
550
-                    fwrite($fh, $buffer);
551
-                } else {
552
-                    $data .= $buffer;
553
-                }
554
-            }
555
-            break;
556
-
557
-        case '8bit':
558
-        case '7bit':
559
-        default:
560
-            while (!feof($fd)) {
561
-                $buffer = fread($fd, 1048576); // 1 MB
562
-                if ($fh) {
563
-                    fwrite($fh, $buffer);
564
-                } else {
565
-                    $data .= $buffer;
566
-                }
567
-            }
568
-        }
569
-
570
-        fclose($fd);
571
-
572
-        if (!$fh) {
573
-            return $data;
574
-        }
575
-    }
576
-
577
-    /**
578
-     * Encodes data to quoted-printable standard.
579
-     *
580
-     * @param string $input    The data to encode
581
-     * @param int    $line_max Optional max line length. Should
582
-     *                         not be more than 76 chars
583
-     *
584
-     * @return string Encoded data
585
-     *
586
-     * @access private
587
-     */
588
-    function _quotedPrintableEncode($input , $line_max = 76)
589
-    {
590
-        $eol = $this->_eol;
591
-        /*
78
+	/**
79
+	 * The encoding type of this part
80
+	 *
81
+	 * @var string
82
+	 * @access private
83
+	 */
84
+	var $_encoding;
85
+
86
+	/**
87
+	 * An array of subparts
88
+	 *
89
+	 * @var array
90
+	 * @access private
91
+	 */
92
+	var $_subparts;
93
+
94
+	/**
95
+	 * The output of this part after being built
96
+	 *
97
+	 * @var string
98
+	 * @access private
99
+	 */
100
+	var $_encoded;
101
+
102
+	/**
103
+	 * Headers for this part
104
+	 *
105
+	 * @var array
106
+	 * @access private
107
+	 */
108
+	var $_headers;
109
+
110
+	/**
111
+	 * The body of this part (not encoded)
112
+	 *
113
+	 * @var string
114
+	 * @access private
115
+	 */
116
+	var $_body;
117
+
118
+	/**
119
+	 * The location of file with body of this part (not encoded)
120
+	 *
121
+	 * @var string
122
+	 * @access private
123
+	 */
124
+	var $_body_file;
125
+
126
+	/**
127
+	 * The end-of-line sequence
128
+	 *
129
+	 * @var string
130
+	 * @access private
131
+	 */
132
+	var $_eol = "\r\n";
133
+
134
+
135
+	/**
136
+	 * Constructor.
137
+	 *
138
+	 * Sets up the object.
139
+	 *
140
+	 * @param string $body   The body of the mime part if any.
141
+	 * @param array  $params An associative array of optional parameters:
142
+	 *     content_type      - The content type for this part eg multipart/mixed
143
+	 *     encoding          - The encoding to use, 7bit, 8bit,
144
+	 *                         base64, or quoted-printable
145
+	 *     charset           - Content character set
146
+	 *     cid               - Content ID to apply
147
+	 *     disposition       - Content disposition, inline or attachment
148
+	 *     filename          - Filename parameter for content disposition
149
+	 *     description       - Content description
150
+	 *     name_encoding     - Encoding of the attachment name (Content-Type)
151
+	 *                         By default filenames are encoded using RFC2231
152
+	 *                         Here you can set RFC2047 encoding (quoted-printable
153
+	 *                         or base64) instead
154
+	 *     filename_encoding - Encoding of the attachment filename (Content-Disposition)
155
+	 *                         See 'name_encoding'
156
+	 *     headers_charset   - Charset of the headers e.g. filename, description.
157
+	 *                         If not set, 'charset' will be used
158
+	 *     eol               - End of line sequence. Default: "\r\n"
159
+	 *     headers           - Hash array with additional part headers. Array keys can be
160
+	 *                         in form of <header_name>:<parameter_name>
161
+	 *     body_file         - Location of file with part's body (instead of $body)
162
+	 *
163
+	 * @access public
164
+	 */
165
+	function Mail_mimePart($body = '', $params = array())
166
+	{
167
+		if (!empty($params['eol'])) {
168
+			$this->_eol = $params['eol'];
169
+		} else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat.
170
+			$this->_eol = MAIL_MIMEPART_CRLF;
171
+		}
172
+
173
+		// Additional part headers
174
+		if (!empty($params['headers']) && is_array($params['headers'])) {
175
+			$headers = $params['headers'];
176
+		}
177
+
178
+		foreach ($params as $key => $value) {
179
+			switch ($key) {
180
+			case 'encoding':
181
+				$this->_encoding = $value;
182
+				$headers['Content-Transfer-Encoding'] = $value;
183
+				break;
184
+
185
+			case 'cid':
186
+				$headers['Content-ID'] = '<' . $value . '>';
187
+				break;
188
+
189
+			case 'location':
190
+				$headers['Content-Location'] = $value;
191
+				break;
192
+
193
+			case 'body_file':
194
+				$this->_body_file = $value;
195
+				break;
196
+
197
+			// for backward compatibility
198
+			case 'dfilename':
199
+				$params['filename'] = $value;
200
+				break;
201
+			}
202
+		}
203
+
204
+		// Default content-type
205
+		if (empty($params['content_type'])) {
206
+			$params['content_type'] = 'text/plain';
207
+		}
208
+
209
+		// Content-Type
210
+		$headers['Content-Type'] = $params['content_type'];
211
+		if (!empty($params['charset'])) {
212
+			$charset = "charset={$params['charset']}";
213
+			// place charset parameter in the same line, if possible
214
+			if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) {
215
+				$headers['Content-Type'] .= '; ';
216
+			} else {
217
+				$headers['Content-Type'] .= ';' . $this->_eol . ' ';
218
+			}
219
+			$headers['Content-Type'] .= $charset;
220
+
221
+			// Default headers charset
222
+			if (!isset($params['headers_charset'])) {
223
+				$params['headers_charset'] = $params['charset'];
224
+			}
225
+		}
226
+
227
+		// header values encoding parameters
228
+		$h_charset  = !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII';
229
+		$h_language = !empty($params['language']) ? $params['language'] : null;
230
+		$h_encoding = !empty($params['name_encoding']) ? $params['name_encoding'] : null;
231
+
232
+
233
+		if (!empty($params['filename'])) {
234
+			$headers['Content-Type'] .= ';' . $this->_eol;
235
+			$headers['Content-Type'] .= $this->_buildHeaderParam(
236
+				'name', $params['filename'], $h_charset, $h_language, $h_encoding
237
+			);
238
+		}
239
+
240
+		// Content-Disposition
241
+		if (!empty($params['disposition'])) {
242
+			$headers['Content-Disposition'] = $params['disposition'];
243
+			if (!empty($params['filename'])) {
244
+				$headers['Content-Disposition'] .= ';' . $this->_eol;
245
+				$headers['Content-Disposition'] .= $this->_buildHeaderParam(
246
+					'filename', $params['filename'], $h_charset, $h_language,
247
+					!empty($params['filename_encoding']) ? $params['filename_encoding'] : null
248
+				);
249
+			}
250
+
251
+			// add attachment size
252
+			$size = $this->_body_file ? filesize($this->_body_file) : strlen($body);
253
+			if ($size) {
254
+				$headers['Content-Disposition'] .= ';' . $this->_eol . ' size=' . $size;
255
+			}
256
+		}
257
+
258
+		if (!empty($params['description'])) {
259
+			$headers['Content-Description'] = $this->encodeHeader(
260
+				'Content-Description', $params['description'], $h_charset, $h_encoding,
261
+				$this->_eol
262
+			);
263
+		}
264
+
265
+		// Search and add existing headers' parameters
266
+		foreach ($headers as $key => $value) {
267
+			$items = explode(':', $key);
268
+			if (count($items) == 2) {
269
+				$header = $items[0];
270
+				$param  = $items[1];
271
+				if (isset($headers[$header])) {
272
+					$headers[$header] .= ';' . $this->_eol;
273
+				}
274
+				$headers[$header] .= $this->_buildHeaderParam(
275
+					$param, $value, $h_charset, $h_language, $h_encoding
276
+				);
277
+				unset($headers[$key]);
278
+			}
279
+		}
280
+
281
+		// Default encoding
282
+		if (!isset($this->_encoding)) {
283
+			$this->_encoding = '7bit';
284
+		}
285
+
286
+		// Assign stuff to member variables
287
+		$this->_encoded  = array();
288
+		$this->_headers  = $headers;
289
+		$this->_body     = $body;
290
+	}
291
+
292
+	/**
293
+	 * Encodes and returns the email. Also stores
294
+	 * it in the encoded member variable
295
+	 *
296
+	 * @param string $boundary Pre-defined boundary string
297
+	 *
298
+	 * @return An associative array containing two elements,
299
+	 *         body and headers. The headers element is itself
300
+	 *         an indexed array. On error returns PEAR error object.
301
+	 * @access public
302
+	 */
303
+	function encode($boundary=null)
304
+	{
305
+		$encoded =& $this->_encoded;
306
+
307
+		if (count($this->_subparts)) {
308
+			$boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
309
+			$eol = $this->_eol;
310
+
311
+			$this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
312
+
313
+			$encoded['body'] = ''; 
314
+
315
+			for ($i = 0; $i < count($this->_subparts); $i++) {
316
+				$encoded['body'] .= '--' . $boundary . $eol;
317
+				$tmp = $this->_subparts[$i]->encode();
318
+				if ($this->_isError($tmp)) {
319
+					return $tmp;
320
+				}
321
+				foreach ($tmp['headers'] as $key => $value) {
322
+					$encoded['body'] .= $key . ': ' . $value . $eol;
323
+				}
324
+				$encoded['body'] .= $eol . $tmp['body'] . $eol;
325
+			}
326
+
327
+			$encoded['body'] .= '--' . $boundary . '--' . $eol;
328
+
329
+		} else if ($this->_body) {
330
+			$encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding);
331
+		} else if ($this->_body_file) {
332
+			// Temporarily reset magic_quotes_runtime for file reads and writes
333
+			if ($magic_quote_setting = get_magic_quotes_runtime()) {
334
+				@ini_set('magic_quotes_runtime', 0);
335
+			}
336
+			$body = $this->_getEncodedDataFromFile($this->_body_file, $this->_encoding);
337
+			if ($magic_quote_setting) {
338
+				@ini_set('magic_quotes_runtime', $magic_quote_setting);
339
+			}
340
+
341
+			if ($this->_isError($body)) {
342
+				return $body;
343
+			}
344
+			$encoded['body'] = $body;
345
+		} else {
346
+			$encoded['body'] = '';
347
+		}
348
+
349
+		// Add headers to $encoded
350
+		$encoded['headers'] =& $this->_headers;
351
+
352
+		return $encoded;
353
+	}
354
+
355
+	/**
356
+	 * Encodes and saves the email into file. File must exist.
357
+	 * Data will be appended to the file.
358
+	 *
359
+	 * @param string  $filename  Output file location
360
+	 * @param string  $boundary  Pre-defined boundary string
361
+	 * @param boolean $skip_head True if you don't want to save headers
362
+	 *
363
+	 * @return array An associative array containing message headers
364
+	 *               or PEAR error object
365
+	 * @access public
366
+	 * @since 1.6.0
367
+	 */
368
+	function encodeToFile($filename, $boundary=null, $skip_head=false)
369
+	{
370
+		if (file_exists($filename) && !is_writable($filename)) {
371
+			$err = $this->_raiseError('File is not writeable: ' . $filename);
372
+			return $err;
373
+		}
374
+
375
+		if (!($fh = fopen($filename, 'ab'))) {
376
+			$err = $this->_raiseError('Unable to open file: ' . $filename);
377
+			return $err;
378
+		}
379
+
380
+		// Temporarily reset magic_quotes_runtime for file reads and writes
381
+		if ($magic_quote_setting = get_magic_quotes_runtime()) {
382
+			@ini_set('magic_quotes_runtime', 0);
383
+		}
384
+
385
+		$res = $this->_encodePartToFile($fh, $boundary, $skip_head);
386
+
387
+		fclose($fh);
388
+
389
+		if ($magic_quote_setting) {
390
+			@ini_set('magic_quotes_runtime', $magic_quote_setting);
391
+		}
392
+
393
+		return $this->_isError($res) ? $res : $this->_headers;
394
+	}
395
+
396
+	/**
397
+	 * Encodes given email part into file
398
+	 *
399
+	 * @param string  $fh        Output file handle
400
+	 * @param string  $boundary  Pre-defined boundary string
401
+	 * @param boolean $skip_head True if you don't want to save headers
402
+	 *
403
+	 * @return array True on sucess or PEAR error object
404
+	 * @access private
405
+	 */
406
+	function _encodePartToFile($fh, $boundary=null, $skip_head=false)
407
+	{
408
+		$eol = $this->_eol;
409
+
410
+		if (count($this->_subparts)) {
411
+			$boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
412
+			$this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
413
+		}
414
+
415
+		if (!$skip_head) {
416
+			foreach ($this->_headers as $key => $value) {
417
+				fwrite($fh, $key . ': ' . $value . $eol);
418
+			}
419
+			$f_eol = $eol;
420
+		} else {
421
+			$f_eol = '';
422
+		}
423
+
424
+		if (count($this->_subparts)) {
425
+			for ($i = 0; $i < count($this->_subparts); $i++) {
426
+				fwrite($fh, $f_eol . '--' . $boundary . $eol);
427
+				$res = $this->_subparts[$i]->_encodePartToFile($fh);
428
+				if ($this->_isError($res)) {
429
+					return $res;
430
+				}
431
+				$f_eol = $eol;
432
+			}
433
+
434
+			fwrite($fh, $eol . '--' . $boundary . '--' . $eol);
435
+
436
+		} else if ($this->_body) {
437
+			fwrite($fh, $f_eol . $this->_getEncodedData($this->_body, $this->_encoding));
438
+		} else if ($this->_body_file) {
439
+			fwrite($fh, $f_eol);
440
+			$res = $this->_getEncodedDataFromFile(
441
+				$this->_body_file, $this->_encoding, $fh
442
+			);
443
+			if ($this->_isError($res)) {
444
+				return $res;
445
+			}
446
+		}
447
+
448
+		return true;
449
+	}
450
+
451
+	/**
452
+	 * Adds a subpart to current mime part and returns
453
+	 * a reference to it
454
+	 *
455
+	 * @param string $body   The body of the subpart, if any.
456
+	 * @param array  $params The parameters for the subpart, same
457
+	 *                       as the $params argument for constructor.
458
+	 *
459
+	 * @return Mail_mimePart A reference to the part you just added. In PHP4, it is
460
+	 *                       crucial if using multipart/* in your subparts that
461
+	 *                       you use =& in your script when calling this function,
462
+	 *                       otherwise you will not be able to add further subparts.
463
+	 * @access public
464
+	 */
465
+	function &addSubpart($body, $params)
466
+	{
467
+		$this->_subparts[] = $part = new Mail_mimePart($body, $params);
468
+		return $part;
469
+	}
470
+
471
+	/**
472
+	 * Returns encoded data based upon encoding passed to it
473
+	 *
474
+	 * @param string $data     The data to encode.
475
+	 * @param string $encoding The encoding type to use, 7bit, base64,
476
+	 *                         or quoted-printable.
477
+	 *
478
+	 * @return string
479
+	 * @access private
480
+	 */
481
+	function _getEncodedData($data, $encoding)
482
+	{
483
+		switch ($encoding) {
484
+		case 'quoted-printable':
485
+			return $this->_quotedPrintableEncode($data);
486
+			break;
487
+
488
+		case 'base64':
489
+			return rtrim(chunk_split(base64_encode($data), 76, $this->_eol));
490
+			break;
491
+
492
+		case '8bit':
493
+		case '7bit':
494
+		default:
495
+			return $data;
496
+		}
497
+	}
498
+
499
+	/**
500
+	 * Returns encoded data based upon encoding passed to it
501
+	 *
502
+	 * @param string   $filename Data file location
503
+	 * @param string   $encoding The encoding type to use, 7bit, base64,
504
+	 *                           or quoted-printable.
505
+	 * @param resource $fh       Output file handle. If set, data will be
506
+	 *                           stored into it instead of returning it
507
+	 *
508
+	 * @return string Encoded data or PEAR error object
509
+	 * @access private
510
+	 */
511
+	function _getEncodedDataFromFile($filename, $encoding, $fh=null)
512
+	{
513
+		if (!is_readable($filename)) {
514
+			$err = $this->_raiseError('Unable to read file: ' . $filename);
515
+			return $err;
516
+		}
517
+
518
+		if (!($fd = fopen($filename, 'rb'))) {
519
+			$err = $this->_raiseError('Could not open file: ' . $filename);
520
+			return $err;
521
+		}
522
+
523
+		$data = '';
524
+
525
+		switch ($encoding) {
526
+		case 'quoted-printable':
527
+			while (!feof($fd)) {
528
+				$buffer = $this->_quotedPrintableEncode(fgets($fd));
529
+				if ($fh) {
530
+					fwrite($fh, $buffer);
531
+				} else {
532
+					$data .= $buffer;
533
+				}
534
+			}
535
+			break;
536
+
537
+		case 'base64':
538
+			while (!feof($fd)) {
539
+				// Should read in a multiple of 57 bytes so that
540
+				// the output is 76 bytes per line. Don't use big chunks
541
+				// because base64 encoding is memory expensive
542
+				$buffer = fread($fd, 57 * 9198); // ca. 0.5 MB
543
+				$buffer = base64_encode($buffer);
544
+				$buffer = chunk_split($buffer, 76, $this->_eol);
545
+				if (feof($fd)) {
546
+					$buffer = rtrim($buffer);
547
+				}
548
+
549
+				if ($fh) {
550
+					fwrite($fh, $buffer);
551
+				} else {
552
+					$data .= $buffer;
553
+				}
554
+			}
555
+			break;
556
+
557
+		case '8bit':
558
+		case '7bit':
559
+		default:
560
+			while (!feof($fd)) {
561
+				$buffer = fread($fd, 1048576); // 1 MB
562
+				if ($fh) {
563
+					fwrite($fh, $buffer);
564
+				} else {
565
+					$data .= $buffer;
566
+				}
567
+			}
568
+		}
569
+
570
+		fclose($fd);
571
+
572
+		if (!$fh) {
573
+			return $data;
574
+		}
575
+	}
576
+
577
+	/**
578
+	 * Encodes data to quoted-printable standard.
579
+	 *
580
+	 * @param string $input    The data to encode
581
+	 * @param int    $line_max Optional max line length. Should
582
+	 *                         not be more than 76 chars
583
+	 *
584
+	 * @return string Encoded data
585
+	 *
586
+	 * @access private
587
+	 */
588
+	function _quotedPrintableEncode($input , $line_max = 76)
589
+	{
590
+		$eol = $this->_eol;
591
+		/*
592 592
         // imap_8bit() is extremely fast, but doesn't handle properly some characters
593 593
         if (function_exists('imap_8bit') && $line_max == 76) {
594 594
             $input = preg_replace('/\r?\n/', "\r\n", $input);
@@ -599,662 +599,662 @@  discard block
 block discarded – undo
599 599
             return $input;
600 600
         }
601 601
         */
602
-        $lines  = preg_split("/\r?\n/", $input);
603
-        $escape = '=';
604
-        $output = '';
605
-
606
-        while (list($idx, $line) = each($lines)) {
607
-            $newline = '';
608
-            $i = 0;
609
-
610
-            while (isset($line[$i])) {
611
-                $char = $line[$i];
612
-                $dec  = ord($char);
613
-                $i++;
614
-
615
-                if (($dec == 32) && (!isset($line[$i]))) {
616
-                    // convert space at eol only
617
-                    $char = '=20';
618
-                } elseif ($dec == 9 && isset($line[$i])) {
619
-                    ; // Do nothing if a TAB is not on eol
620
-                } elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) {
621
-                    $char = $escape . sprintf('%02X', $dec);
622
-                } elseif (($dec == 46) && (($newline == '')
623
-                    || ((strlen($newline) + strlen("=2E")) >= $line_max))
624
-                ) {
625
-                    // Bug #9722: convert full-stop at bol,
626
-                    // some Windows servers need this, won't break anything (cipri)
627
-                    // Bug #11731: full-stop at bol also needs to be encoded
628
-                    // if this line would push us over the line_max limit.
629
-                    $char = '=2E';
630
-                }
631
-
632
-                // Note, when changing this line, also change the ($dec == 46)
633
-                // check line, as it mimics this line due to Bug #11731
634
-                // EOL is not counted
635
-                if ((strlen($newline) + strlen($char)) >= $line_max) {
636
-                    // soft line break; " =\r\n" is okay
637
-                    $output  .= $newline . $escape . $eol;
638
-                    $newline  = '';
639
-                }
640
-                $newline .= $char;
641
-            } // end of for
642
-            $output .= $newline . $eol;
643
-            unset($lines[$idx]);
644
-        }
645
-        // Don't want last crlf
646
-        $output = substr($output, 0, -1 * strlen($eol));
647
-        return $output;
648
-    }
649
-
650
-    /**
651
-     * Encodes the parameter of a header.
652
-     *
653
-     * @param string $name      The name of the header-parameter
654
-     * @param string $value     The value of the paramter
655
-     * @param string $charset   The characterset of $value
656
-     * @param string $language  The language used in $value
657
-     * @param string $encoding  Parameter encoding. If not set, parameter value
658
-     *                          is encoded according to RFC2231
659
-     * @param int    $maxLength The maximum length of a line. Defauls to 75
660
-     *
661
-     * @return string
662
-     *
663
-     * @access private
664
-     */
665
-    function _buildHeaderParam($name, $value, $charset=null, $language=null,
666
-        $encoding=null, $maxLength=75
667
-    ) {
668
-        // RFC 2045:
669
-        // value needs encoding if contains non-ASCII chars or is longer than 78 chars
670
-        if (!preg_match('#[^\x20-\x7E]#', $value)) {
671
-            $token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
672
-                . '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
673
-            if (!preg_match($token_regexp, $value)) {
674
-                // token
675
-                if (strlen($name) + strlen($value) + 3 <= $maxLength) {
676
-                    return " {$name}={$value}";
677
-                }
678
-            } else {
679
-                // quoted-string
680
-                $quoted = addcslashes($value, '\\"');
681
-                if (strlen($name) + strlen($quoted) + 5 <= $maxLength) {
682
-                    return " {$name}=\"{$quoted}\"";
683
-                }
684
-            }
685
-        }
686
-
687
-        // RFC2047: use quoted-printable/base64 encoding
688
-        if ($encoding == 'quoted-printable' || $encoding == 'base64') {
689
-            return $this->_buildRFC2047Param($name, $value, $charset, $encoding);
690
-        }
691
-
692
-        // RFC2231:
693
-        $encValue = preg_replace_callback(
694
-            '/([^\x21\x23\x24\x26\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])/',
695
-            array($this, '_encodeReplaceCallback'), $value
696
-        );
697
-        $value = "$charset'$language'$encValue";
698
-
699
-        $header = " {$name}*={$value}";
700
-        if (strlen($header) <= $maxLength) {
701
-            return $header;
702
-        }
703
-
704
-        $preLength = strlen(" {$name}*0*=");
705
-        $maxLength = max(16, $maxLength - $preLength - 3);
706
-        $maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|";
707
-
708
-        $headers = array();
709
-        $headCount = 0;
710
-        while ($value) {
711
-            $matches = array();
712
-            $found = preg_match($maxLengthReg, $value, $matches);
713
-            if ($found) {
714
-                $headers[] = " {$name}*{$headCount}*={$matches[0]}";
715
-                $value = substr($value, strlen($matches[0]));
716
-            } else {
717
-                $headers[] = " {$name}*{$headCount}*={$value}";
718
-                $value = '';
719
-            }
720
-            $headCount++;
721
-        }
722
-
723
-        $headers = implode(';' . $this->_eol, $headers);
724
-        return $headers;
725
-    }
726
-
727
-    /**
728
-     * Encodes header parameter as per RFC2047 if needed
729
-     *
730
-     * @param string $name      The parameter name
731
-     * @param string $value     The parameter value
732
-     * @param string $charset   The parameter charset
733
-     * @param string $encoding  Encoding type (quoted-printable or base64)
734
-     * @param int    $maxLength Encoded parameter max length. Default: 76
735
-     *
736
-     * @return string Parameter line
737
-     * @access private
738
-     */
739
-    function _buildRFC2047Param($name, $value, $charset,
740
-        $encoding='quoted-printable', $maxLength=76
741
-    ) {
742
-        // WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in
743
-        // parameter of a MIME Content-Type or Content-Disposition field",
744
-        // but... it's supported by many clients/servers
745
-        $quoted = '';
746
-
747
-        if ($encoding == 'base64') {
748
-            $value = base64_encode($value);
749
-            $prefix = '=?' . $charset . '?B?';
750
-            $suffix = '?=';
751
-
752
-            // 2 x SPACE, 2 x '"', '=', ';'
753
-            $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
754
-            $len = $add_len + strlen($value);
755
-
756
-            while ($len > $maxLength) { 
757
-                // We can cut base64-encoded string every 4 characters
758
-                $real_len = floor(($maxLength - $add_len) / 4) * 4;
759
-                $_quote = substr($value, 0, $real_len);
760
-                $value = substr($value, $real_len);
761
-
762
-                $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
763
-                $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
764
-                $len = strlen($value) + $add_len;
765
-            }
766
-            $quoted .= $prefix . $value . $suffix;
767
-
768
-        } else {
769
-            // quoted-printable
770
-            $value = $this->encodeQP($value);
771
-            $prefix = '=?' . $charset . '?Q?';
772
-            $suffix = '?=';
773
-
774
-            // 2 x SPACE, 2 x '"', '=', ';'
775
-            $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
776
-            $len = $add_len + strlen($value);
777
-
778
-            while ($len > $maxLength) {
779
-                $length = $maxLength - $add_len;
780
-                // don't break any encoded letters
781
-                if (preg_match("/^(.{0,$length}[^\=][^\=])/", $value, $matches)) {
782
-                    $_quote = $matches[1];
783
-                }
784
-
785
-                $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
786
-                $value = substr($value, strlen($_quote));
787
-                $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
788
-                $len = strlen($value) + $add_len;
789
-            }
790
-
791
-            $quoted .= $prefix . $value . $suffix;
792
-        }
793
-
794
-        return " {$name}=\"{$quoted}\"";
795
-    }
796
-
797
-    /**
798
-     * Encodes a header as per RFC2047
799
-     *
800
-     * @param string $name     The header name
801
-     * @param string $value    The header data to encode
802
-     * @param string $charset  Character set name
803
-     * @param string $encoding Encoding name (base64 or quoted-printable)
804
-     * @param string $eol      End-of-line sequence. Default: "\r\n"
805
-     *
806
-     * @return string          Encoded header data (without a name)
807
-     * @access public
808
-     * @since 1.6.1
809
-     */
810
-    function encodeHeader($name, $value, $charset='ISO-8859-1',
811
-        $encoding='quoted-printable', $eol="\r\n"
812
-    ) {
813
-        // Structured headers
814
-        $comma_headers = array(
815
-            'from', 'to', 'cc', 'bcc', 'sender', 'reply-to',
816
-            'resent-from', 'resent-to', 'resent-cc', 'resent-bcc',
817
-            'resent-sender', 'resent-reply-to',
818
-            'mail-reply-to', 'mail-followup-to',
819
-            'return-receipt-to', 'disposition-notification-to',
820
-        );
821
-        $other_headers = array(
822
-            'references', 'in-reply-to', 'message-id', 'resent-message-id',
823
-        );
824
-
825
-        $name = strtolower($name);
826
-
827
-        if (in_array($name, $comma_headers)) {
828
-            $separator = ',';
829
-        } else if (in_array($name, $other_headers)) {
830
-            $separator = ' ';
831
-        }
832
-
833
-        if (!$charset) {
834
-            $charset = 'ISO-8859-1';
835
-        }
836
-
837
-        // Structured header (make sure addr-spec inside is not encoded)
838
-        if (!empty($separator)) {
839
-            // Simple e-mail address regexp
840
-            $email_regexp = '([^\s<]+|("[^\r\n"]+"))@\S+';
841
-
842
-            $parts = Mail_mimePart::_explodeQuotedString("[\t$separator]", $value);
843
-            $value = '';
844
-
845
-            foreach ($parts as $part) {
846
-                $part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part);
847
-                $part = trim($part);
848
-
849
-                if (!$part) {
850
-                    continue;
851
-                }
852
-                if ($value) {
853
-                    $value .= $separator == ',' ? $separator . ' ' : ' ';
854
-                } else {
855
-                    $value = $name . ': ';
856
-                }
857
-
858
-                // let's find phrase (name) and/or addr-spec
859
-                if (preg_match('/^<' . $email_regexp . '>$/', $part)) {
860
-                    $value .= $part;
861
-                } else if (preg_match('/^' . $email_regexp . '$/', $part)) {
862
-                    // address without brackets and without name
863
-                    $value .= $part;
864
-                } else if (preg_match('/<*' . $email_regexp . '>*$/', $part, $matches)) {
865
-                    // address with name (handle name)
866
-                    $address = $matches[0];
867
-                    $word = str_replace($address, '', $part);
868
-                    $word = trim($word);
869
-                    // check if phrase requires quoting
870
-                    if ($word) {
871
-                        // non-ASCII: require encoding
872
-                        if (preg_match('#([^\s\x21-\x7E]){1}#', $word)) {
873
-                            if ($word[0] == '"' && $word[strlen($word)-1] == '"') {
874
-                                // de-quote quoted-string, encoding changes
875
-                                // string to atom
876
-                                $search = array("\\\"", "\\\\");
877
-                                $replace = array("\"", "\\");
878
-                                $word = str_replace($search, $replace, $word);
879
-                                $word = substr($word, 1, -1);
880
-                            }
881
-                            // find length of last line
882
-                            if (($pos = strrpos($value, $eol)) !== false) {
883
-                                $last_len = strlen($value) - $pos;
884
-                            } else {
885
-                                $last_len = strlen($value);
886
-                            }
887
-                            $word = Mail_mimePart::encodeHeaderValue(
888
-                                $word, $charset, $encoding, $last_len, $eol
889
-                            );
890
-                        } else if (($word[0] != '"' || $word[strlen($word)-1] != '"')
891
-                            && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word)
892
-                        ) {
893
-                            // ASCII: quote string if needed
894
-                            $word = '"'.addcslashes($word, '\\"').'"';
895
-                        }
896
-                    }
897
-                    $value .= $word.' '.$address;
898
-                } else {
899
-                    // addr-spec not found, don't encode (?)
900
-                    $value .= $part;
901
-                }
902
-
903
-                // RFC2822 recommends 78 characters limit, use 76 from RFC2047
904
-                $value = wordwrap($value, 76, $eol . ' ');
905
-            }
906
-
907
-            // remove header name prefix (there could be EOL too)
908
-            $value = preg_replace(
909
-                '/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value
910
-            );
911
-        } else {
912
-            // Unstructured header
913
-            // non-ASCII: require encoding
914
-            if (preg_match('#([^\s\x21-\x7E]){1}#', $value)) {
915
-                if ($value[0] == '"' && $value[strlen($value)-1] == '"') {
916
-                    // de-quote quoted-string, encoding changes
917
-                    // string to atom
918
-                    $search = array("\\\"", "\\\\");
919
-                    $replace = array("\"", "\\");
920
-                    $value = str_replace($search, $replace, $value);
921
-                    $value = substr($value, 1, -1);
922
-                }
923
-                $value = Mail_mimePart::encodeHeaderValue(
924
-                    $value, $charset, $encoding, strlen($name) + 2, $eol
925
-                );
926
-            } else if (strlen($name.': '.$value) > 78) {
927
-                // ASCII: check if header line isn't too long and use folding
928
-                $value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value);
929
-                $tmp = wordwrap($name.': '.$value, 78, $eol . ' ');
930
-                $value = preg_replace('/^'.$name.':\s*/', '', $tmp);
931
-                // hard limit 998 (RFC2822)
932
-                $value = wordwrap($value, 998, $eol . ' ', true);
933
-            }
934
-        }
935
-
936
-        return $value;
937
-    }
938
-
939
-    /**
940
-     * Explode quoted string
941
-     *
942
-     * @param string $delimiter Delimiter expression string for preg_match()
943
-     * @param string $string    Input string
944
-     *
945
-     * @return array            String tokens array
946
-     * @access private
947
-     */
948
-    function _explodeQuotedString($delimiter, $string)
949
-    {
950
-        $result = array();
951
-        $strlen = strlen($string);
952
-
953
-        for ($q=$p=$i=0; $i < $strlen; $i++) {
954
-            if ($string[$i] == "\""
955
-                && (empty($string[$i-1]) || $string[$i-1] != "\\")
956
-            ) {
957
-                $q = $q ? false : true;
958
-            } else if (!$q && preg_match("/$delimiter/", $string[$i])) {
959
-                $result[] = substr($string, $p, $i - $p);
960
-                $p = $i + 1;
961
-            }
962
-        }
963
-
964
-        $result[] = substr($string, $p);
965
-        return $result;
966
-    }
967
-
968
-    /**
969
-     * Encodes a header value as per RFC2047
970
-     *
971
-     * @param string $value      The header data to encode
972
-     * @param string $charset    Character set name
973
-     * @param string $encoding   Encoding name (base64 or quoted-printable)
974
-     * @param int    $prefix_len Prefix length. Default: 0
975
-     * @param string $eol        End-of-line sequence. Default: "\r\n"
976
-     *
977
-     * @return string            Encoded header data
978
-     * @access public
979
-     * @since 1.6.1
980
-     */
981
-    function encodeHeaderValue($value, $charset, $encoding, $prefix_len=0, $eol="\r\n")
982
-    {
983
-        // #17311: Use multibyte aware method (requires mbstring extension)
984
-        if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) {
985
-            return $result;
986
-        }
987
-
988
-        // Generate the header using the specified params and dynamicly
989
-        // determine the maximum length of such strings.
990
-        // 75 is the value specified in the RFC.
991
-        $encoding = $encoding == 'base64' ? 'B' : 'Q';
992
-        $prefix = '=?' . $charset . '?' . $encoding .'?';
993
-        $suffix = '?=';
994
-        $maxLength = 75 - strlen($prefix . $suffix);
995
-        $maxLength1stLine = $maxLength - $prefix_len;
996
-
997
-        if ($encoding == 'B') {
998
-            // Base64 encode the entire string
999
-            $value = base64_encode($value);
1000
-
1001
-            // We can cut base64 every 4 characters, so the real max
1002
-            // we can get must be rounded down.
1003
-            $maxLength = $maxLength - ($maxLength % 4);
1004
-            $maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4);
1005
-
1006
-            $cutpoint = $maxLength1stLine;
1007
-            $output = '';
1008
-
1009
-            while ($value) {
1010
-                // Split translated string at every $maxLength
1011
-                $part = substr($value, 0, $cutpoint);
1012
-                $value = substr($value, $cutpoint);
1013
-                $cutpoint = $maxLength;
1014
-                // RFC 2047 specifies that any split header should
1015
-                // be separated by a CRLF SPACE.
1016
-                if ($output) {
1017
-                    $output .= $eol . ' ';
1018
-                }
1019
-                $output .= $prefix . $part . $suffix;
1020
-            }
1021
-            $value = $output;
1022
-        } else {
1023
-            // quoted-printable encoding has been selected
1024
-            $value = Mail_mimePart::encodeQP($value);
1025
-
1026
-            // This regexp will break QP-encoded text at every $maxLength
1027
-            // but will not break any encoded letters.
1028
-            $reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|";
1029
-            $reg2nd = "|(.{0,$maxLength}[^\=][^\=])|";
1030
-
1031
-            if (strlen($value) > $maxLength1stLine) {
1032
-                // Begin with the regexp for the first line.
1033
-                $reg = $reg1st;
1034
-                $output = '';
1035
-                while ($value) {
1036
-                    // Split translated string at every $maxLength
1037
-                    // But make sure not to break any translated chars.
1038
-                    $found = preg_match($reg, $value, $matches);
1039
-
1040
-                    // After this first line, we need to use a different
1041
-                    // regexp for the first line.
1042
-                    $reg = $reg2nd;
1043
-
1044
-                    // Save the found part and encapsulate it in the
1045
-                    // prefix & suffix. Then remove the part from the
1046
-                    // $value_out variable.
1047
-                    if ($found) {
1048
-                        $part = $matches[0];
1049
-                        $len = strlen($matches[0]);
1050
-                        $value = substr($value, $len);
1051
-                    } else {
1052
-                        $part = $value;
1053
-                        $value = '';
1054
-                    }
1055
-
1056
-                    // RFC 2047 specifies that any split header should
1057
-                    // be separated by a CRLF SPACE
1058
-                    if ($output) {
1059
-                        $output .= $eol . ' ';
1060
-                    }
1061
-                    $output .= $prefix . $part . $suffix;
1062
-                }
1063
-                $value = $output;
1064
-            } else {
1065
-                $value = $prefix . $value . $suffix;
1066
-            }
1067
-        }
1068
-
1069
-        return $value;
1070
-    }
1071
-
1072
-    /**
1073
-     * Encodes the given string using quoted-printable
1074
-     *
1075
-     * @param string $str String to encode
1076
-     *
1077
-     * @return string     Encoded string
1078
-     * @access public
1079
-     * @since 1.6.0
1080
-     */
1081
-    function encodeQP($str)
1082
-    {
1083
-        // Bug #17226 RFC 2047 restricts some characters
1084
-        // if the word is inside a phrase, permitted chars are only:
1085
-        // ASCII letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
1086
-
1087
-        // "=",  "_",  "?" must be encoded
1088
-        $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
1089
-        $str = preg_replace_callback(
1090
-            $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $str
1091
-        );
1092
-
1093
-        return str_replace(' ', '_', $str);
1094
-    }
1095
-
1096
-    /**
1097
-     * Encodes the given string using base64 or quoted-printable.
1098
-     * This method makes sure that encoded-word represents an integral
1099
-     * number of characters as per RFC2047.
1100
-     *
1101
-     * @param string $str        String to encode
1102
-     * @param string $charset    Character set name
1103
-     * @param string $encoding   Encoding name (base64 or quoted-printable)
1104
-     * @param int    $prefix_len Prefix length. Default: 0
1105
-     * @param string $eol        End-of-line sequence. Default: "\r\n"
1106
-     *
1107
-     * @return string     Encoded string
1108
-     * @access public
1109
-     * @since 1.8.0
1110
-     */
1111
-    function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n")
1112
-    {
1113
-        if (!function_exists('mb_substr') || !function_exists('mb_strlen')) {
1114
-            return;
1115
-        }
1116
-
1117
-        $encoding = $encoding == 'base64' ? 'B' : 'Q';
1118
-        // 75 is the value specified in the RFC
1119
-        $prefix = '=?' . $charset . '?'.$encoding.'?';
1120
-        $suffix = '?=';
1121
-        $maxLength = 75 - strlen($prefix . $suffix);
1122
-
1123
-        // A multi-octet character may not be split across adjacent encoded-words
1124
-        // So, we'll loop over each character
1125
-        // mb_stlen() with wrong charset will generate a warning here and return null
1126
-        $length      = mb_strlen($str, $charset);
1127
-        $result      = '';
1128
-        $line_length = $prefix_len;
1129
-
1130
-        if ($encoding == 'B') {
1131
-            // base64
1132
-            $start = 0;
1133
-            $prev  = '';
1134
-
1135
-            for ($i=1; $i<=$length; $i++) {
1136
-                // See #17311
1137
-                $chunk = mb_substr($str, $start, $i-$start, $charset);
1138
-                $chunk = base64_encode($chunk);
1139
-                $chunk_len = strlen($chunk);
1140
-
1141
-                if ($line_length + $chunk_len == $maxLength || $i == $length) {
1142
-                    if ($result) {
1143
-                        $result .= "\n";
1144
-                    }
1145
-                    $result .= $chunk;
1146
-                    $line_length = 0;
1147
-                    $start = $i;
1148
-                } else if ($line_length + $chunk_len > $maxLength) {
1149
-                    if ($result) {
1150
-                        $result .= "\n";
1151
-                    }
1152
-                    if ($prev) {
1153
-                        $result .= $prev;
1154
-                    }
1155
-                    $line_length = 0;
1156
-                    $start = $i - 1;
1157
-                } else {
1158
-                    $prev = $chunk;
1159
-                }
1160
-            }
1161
-        } else {
1162
-            // quoted-printable
1163
-            // see encodeQP()
1164
-            $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
1165
-
1166
-            for ($i=0; $i<=$length; $i++) {
1167
-                $char = mb_substr($str, $i, 1, $charset);
1168
-                // RFC recommends underline (instead of =20) in place of the space
1169
-                // that's one of the reasons why we're not using iconv_mime_encode()
1170
-                if ($char == ' ') {
1171
-                    $char = '_';
1172
-                    $char_len = 1;
1173
-                } else {
1174
-                    $char = preg_replace_callback(
1175
-                        $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $char
1176
-                    );
1177
-                    $char_len = strlen($char);
1178
-                }
1179
-
1180
-                if ($line_length + $char_len > $maxLength) {
1181
-                    if ($result) {
1182
-                        $result .= "\n";
1183
-                    }
1184
-                    $line_length = 0;
1185
-                }
1186
-
1187
-                $result      .= $char;
1188
-                $line_length += $char_len;
1189
-            }
1190
-        }
1191
-
1192
-        if ($result) {
1193
-            $result = $prefix
1194
-                .str_replace("\n", $suffix.$eol.' '.$prefix, $result).$suffix;
1195
-        }
1196
-
1197
-        return $result;
1198
-    }
1199
-
1200
-    /**
1201
-     * Callback function to replace extended characters (\x80-xFF) with their
1202
-     * ASCII values (RFC2047: quoted-printable)
1203
-     *
1204
-     * @param array $matches Preg_replace's matches array
1205
-     *
1206
-     * @return string        Encoded character string
1207
-     * @access private
1208
-     */
1209
-    function _qpReplaceCallback($matches)
1210
-    {
1211
-        return sprintf('=%02X', ord($matches[1]));
1212
-    }
1213
-
1214
-    /**
1215
-     * Callback function to replace extended characters (\x80-xFF) with their
1216
-     * ASCII values (RFC2231)
1217
-     *
1218
-     * @param array $matches Preg_replace's matches array
1219
-     *
1220
-     * @return string        Encoded character string
1221
-     * @access private
1222
-     */
1223
-    function _encodeReplaceCallback($matches)
1224
-    {
1225
-        return sprintf('%%%02X', ord($matches[1]));
1226
-    }
1227
-
1228
-    /**
1229
-     * PEAR::isError implementation
1230
-     *
1231
-     * @param mixed $data Object
1232
-     *
1233
-     * @return bool True if object is an instance of PEAR_Error
1234
-     * @access private
1235
-     */
1236
-    function _isError($data)
1237
-    {
1238
-        // PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
1239
-        if (is_object($data) && is_a($data, 'PEAR_Error')) {
1240
-            return true;
1241
-        }
1242
-
1243
-        return false;
1244
-    }
1245
-
1246
-    /**
1247
-     * PEAR::raiseError implementation
1248
-     *
1249
-     * @param $message A text error message
1250
-     *
1251
-     * @return PEAR_Error Instance of PEAR_Error
1252
-     * @access private
1253
-     */
1254
-    function _raiseError($message)
1255
-    {
1256
-        // PEAR::raiseError() is not PHP 5.4 compatible
1257
-        return new PEAR_Error($message);
1258
-    }
602
+		$lines  = preg_split("/\r?\n/", $input);
603
+		$escape = '=';
604
+		$output = '';
605
+
606
+		while (list($idx, $line) = each($lines)) {
607
+			$newline = '';
608
+			$i = 0;
609
+
610
+			while (isset($line[$i])) {
611
+				$char = $line[$i];
612
+				$dec  = ord($char);
613
+				$i++;
614
+
615
+				if (($dec == 32) && (!isset($line[$i]))) {
616
+					// convert space at eol only
617
+					$char = '=20';
618
+				} elseif ($dec == 9 && isset($line[$i])) {
619
+					; // Do nothing if a TAB is not on eol
620
+				} elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) {
621
+					$char = $escape . sprintf('%02X', $dec);
622
+				} elseif (($dec == 46) && (($newline == '')
623
+					|| ((strlen($newline) + strlen("=2E")) >= $line_max))
624
+				) {
625
+					// Bug #9722: convert full-stop at bol,
626
+					// some Windows servers need this, won't break anything (cipri)
627
+					// Bug #11731: full-stop at bol also needs to be encoded
628
+					// if this line would push us over the line_max limit.
629
+					$char = '=2E';
630
+				}
631
+
632
+				// Note, when changing this line, also change the ($dec == 46)
633
+				// check line, as it mimics this line due to Bug #11731
634
+				// EOL is not counted
635
+				if ((strlen($newline) + strlen($char)) >= $line_max) {
636
+					// soft line break; " =\r\n" is okay
637
+					$output  .= $newline . $escape . $eol;
638
+					$newline  = '';
639
+				}
640
+				$newline .= $char;
641
+			} // end of for
642
+			$output .= $newline . $eol;
643
+			unset($lines[$idx]);
644
+		}
645
+		// Don't want last crlf
646
+		$output = substr($output, 0, -1 * strlen($eol));
647
+		return $output;
648
+	}
649
+
650
+	/**
651
+	 * Encodes the parameter of a header.
652
+	 *
653
+	 * @param string $name      The name of the header-parameter
654
+	 * @param string $value     The value of the paramter
655
+	 * @param string $charset   The characterset of $value
656
+	 * @param string $language  The language used in $value
657
+	 * @param string $encoding  Parameter encoding. If not set, parameter value
658
+	 *                          is encoded according to RFC2231
659
+	 * @param int    $maxLength The maximum length of a line. Defauls to 75
660
+	 *
661
+	 * @return string
662
+	 *
663
+	 * @access private
664
+	 */
665
+	function _buildHeaderParam($name, $value, $charset=null, $language=null,
666
+		$encoding=null, $maxLength=75
667
+	) {
668
+		// RFC 2045:
669
+		// value needs encoding if contains non-ASCII chars or is longer than 78 chars
670
+		if (!preg_match('#[^\x20-\x7E]#', $value)) {
671
+			$token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
672
+				. '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
673
+			if (!preg_match($token_regexp, $value)) {
674
+				// token
675
+				if (strlen($name) + strlen($value) + 3 <= $maxLength) {
676
+					return " {$name}={$value}";
677
+				}
678
+			} else {
679
+				// quoted-string
680
+				$quoted = addcslashes($value, '\\"');
681
+				if (strlen($name) + strlen($quoted) + 5 <= $maxLength) {
682
+					return " {$name}=\"{$quoted}\"";
683
+				}
684
+			}
685
+		}
686
+
687
+		// RFC2047: use quoted-printable/base64 encoding
688
+		if ($encoding == 'quoted-printable' || $encoding == 'base64') {
689
+			return $this->_buildRFC2047Param($name, $value, $charset, $encoding);
690
+		}
691
+
692
+		// RFC2231:
693
+		$encValue = preg_replace_callback(
694
+			'/([^\x21\x23\x24\x26\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])/',
695
+			array($this, '_encodeReplaceCallback'), $value
696
+		);
697
+		$value = "$charset'$language'$encValue";
698
+
699
+		$header = " {$name}*={$value}";
700
+		if (strlen($header) <= $maxLength) {
701
+			return $header;
702
+		}
703
+
704
+		$preLength = strlen(" {$name}*0*=");
705
+		$maxLength = max(16, $maxLength - $preLength - 3);
706
+		$maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|";
707
+
708
+		$headers = array();
709
+		$headCount = 0;
710
+		while ($value) {
711
+			$matches = array();
712
+			$found = preg_match($maxLengthReg, $value, $matches);
713
+			if ($found) {
714
+				$headers[] = " {$name}*{$headCount}*={$matches[0]}";
715
+				$value = substr($value, strlen($matches[0]));
716
+			} else {
717
+				$headers[] = " {$name}*{$headCount}*={$value}";
718
+				$value = '';
719
+			}
720
+			$headCount++;
721
+		}
722
+
723
+		$headers = implode(';' . $this->_eol, $headers);
724
+		return $headers;
725
+	}
726
+
727
+	/**
728
+	 * Encodes header parameter as per RFC2047 if needed
729
+	 *
730
+	 * @param string $name      The parameter name
731
+	 * @param string $value     The parameter value
732
+	 * @param string $charset   The parameter charset
733
+	 * @param string $encoding  Encoding type (quoted-printable or base64)
734
+	 * @param int    $maxLength Encoded parameter max length. Default: 76
735
+	 *
736
+	 * @return string Parameter line
737
+	 * @access private
738
+	 */
739
+	function _buildRFC2047Param($name, $value, $charset,
740
+		$encoding='quoted-printable', $maxLength=76
741
+	) {
742
+		// WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in
743
+		// parameter of a MIME Content-Type or Content-Disposition field",
744
+		// but... it's supported by many clients/servers
745
+		$quoted = '';
746
+
747
+		if ($encoding == 'base64') {
748
+			$value = base64_encode($value);
749
+			$prefix = '=?' . $charset . '?B?';
750
+			$suffix = '?=';
751
+
752
+			// 2 x SPACE, 2 x '"', '=', ';'
753
+			$add_len = strlen($prefix . $suffix) + strlen($name) + 6;
754
+			$len = $add_len + strlen($value);
755
+
756
+			while ($len > $maxLength) { 
757
+				// We can cut base64-encoded string every 4 characters
758
+				$real_len = floor(($maxLength - $add_len) / 4) * 4;
759
+				$_quote = substr($value, 0, $real_len);
760
+				$value = substr($value, $real_len);
761
+
762
+				$quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
763
+				$add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
764
+				$len = strlen($value) + $add_len;
765
+			}
766
+			$quoted .= $prefix . $value . $suffix;
767
+
768
+		} else {
769
+			// quoted-printable
770
+			$value = $this->encodeQP($value);
771
+			$prefix = '=?' . $charset . '?Q?';
772
+			$suffix = '?=';
773
+
774
+			// 2 x SPACE, 2 x '"', '=', ';'
775
+			$add_len = strlen($prefix . $suffix) + strlen($name) + 6;
776
+			$len = $add_len + strlen($value);
777
+
778
+			while ($len > $maxLength) {
779
+				$length = $maxLength - $add_len;
780
+				// don't break any encoded letters
781
+				if (preg_match("/^(.{0,$length}[^\=][^\=])/", $value, $matches)) {
782
+					$_quote = $matches[1];
783
+				}
784
+
785
+				$quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
786
+				$value = substr($value, strlen($_quote));
787
+				$add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
788
+				$len = strlen($value) + $add_len;
789
+			}
790
+
791
+			$quoted .= $prefix . $value . $suffix;
792
+		}
793
+
794
+		return " {$name}=\"{$quoted}\"";
795
+	}
796
+
797
+	/**
798
+	 * Encodes a header as per RFC2047
799
+	 *
800
+	 * @param string $name     The header name
801
+	 * @param string $value    The header data to encode
802
+	 * @param string $charset  Character set name
803
+	 * @param string $encoding Encoding name (base64 or quoted-printable)
804
+	 * @param string $eol      End-of-line sequence. Default: "\r\n"
805
+	 *
806
+	 * @return string          Encoded header data (without a name)
807
+	 * @access public
808
+	 * @since 1.6.1
809
+	 */
810
+	function encodeHeader($name, $value, $charset='ISO-8859-1',
811
+		$encoding='quoted-printable', $eol="\r\n"
812
+	) {
813
+		// Structured headers
814
+		$comma_headers = array(
815
+			'from', 'to', 'cc', 'bcc', 'sender', 'reply-to',
816
+			'resent-from', 'resent-to', 'resent-cc', 'resent-bcc',
817
+			'resent-sender', 'resent-reply-to',
818
+			'mail-reply-to', 'mail-followup-to',
819
+			'return-receipt-to', 'disposition-notification-to',
820
+		);
821
+		$other_headers = array(
822
+			'references', 'in-reply-to', 'message-id', 'resent-message-id',
823
+		);
824
+
825
+		$name = strtolower($name);
826
+
827
+		if (in_array($name, $comma_headers)) {
828
+			$separator = ',';
829
+		} else if (in_array($name, $other_headers)) {
830
+			$separator = ' ';
831
+		}
832
+
833
+		if (!$charset) {
834
+			$charset = 'ISO-8859-1';
835
+		}
836
+
837
+		// Structured header (make sure addr-spec inside is not encoded)
838
+		if (!empty($separator)) {
839
+			// Simple e-mail address regexp
840
+			$email_regexp = '([^\s<]+|("[^\r\n"]+"))@\S+';
841
+
842
+			$parts = Mail_mimePart::_explodeQuotedString("[\t$separator]", $value);
843
+			$value = '';
844
+
845
+			foreach ($parts as $part) {
846
+				$part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part);
847
+				$part = trim($part);
848
+
849
+				if (!$part) {
850
+					continue;
851
+				}
852
+				if ($value) {
853
+					$value .= $separator == ',' ? $separator . ' ' : ' ';
854
+				} else {
855
+					$value = $name . ': ';
856
+				}
857
+
858
+				// let's find phrase (name) and/or addr-spec
859
+				if (preg_match('/^<' . $email_regexp . '>$/', $part)) {
860
+					$value .= $part;
861
+				} else if (preg_match('/^' . $email_regexp . '$/', $part)) {
862
+					// address without brackets and without name
863
+					$value .= $part;
864
+				} else if (preg_match('/<*' . $email_regexp . '>*$/', $part, $matches)) {
865
+					// address with name (handle name)
866
+					$address = $matches[0];
867
+					$word = str_replace($address, '', $part);
868
+					$word = trim($word);
869
+					// check if phrase requires quoting
870
+					if ($word) {
871
+						// non-ASCII: require encoding
872
+						if (preg_match('#([^\s\x21-\x7E]){1}#', $word)) {
873
+							if ($word[0] == '"' && $word[strlen($word)-1] == '"') {
874
+								// de-quote quoted-string, encoding changes
875
+								// string to atom
876
+								$search = array("\\\"", "\\\\");
877
+								$replace = array("\"", "\\");
878
+								$word = str_replace($search, $replace, $word);
879
+								$word = substr($word, 1, -1);
880
+							}
881
+							// find length of last line
882
+							if (($pos = strrpos($value, $eol)) !== false) {
883
+								$last_len = strlen($value) - $pos;
884
+							} else {
885
+								$last_len = strlen($value);
886
+							}
887
+							$word = Mail_mimePart::encodeHeaderValue(
888
+								$word, $charset, $encoding, $last_len, $eol
889
+							);
890
+						} else if (($word[0] != '"' || $word[strlen($word)-1] != '"')
891
+							&& preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word)
892
+						) {
893
+							// ASCII: quote string if needed
894
+							$word = '"'.addcslashes($word, '\\"').'"';
895
+						}
896
+					}
897
+					$value .= $word.' '.$address;
898
+				} else {
899
+					// addr-spec not found, don't encode (?)
900
+					$value .= $part;
901
+				}
902
+
903
+				// RFC2822 recommends 78 characters limit, use 76 from RFC2047
904
+				$value = wordwrap($value, 76, $eol . ' ');
905
+			}
906
+
907
+			// remove header name prefix (there could be EOL too)
908
+			$value = preg_replace(
909
+				'/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value
910
+			);
911
+		} else {
912
+			// Unstructured header
913
+			// non-ASCII: require encoding
914
+			if (preg_match('#([^\s\x21-\x7E]){1}#', $value)) {
915
+				if ($value[0] == '"' && $value[strlen($value)-1] == '"') {
916
+					// de-quote quoted-string, encoding changes
917
+					// string to atom
918
+					$search = array("\\\"", "\\\\");
919
+					$replace = array("\"", "\\");
920
+					$value = str_replace($search, $replace, $value);
921
+					$value = substr($value, 1, -1);
922
+				}
923
+				$value = Mail_mimePart::encodeHeaderValue(
924
+					$value, $charset, $encoding, strlen($name) + 2, $eol
925
+				);
926
+			} else if (strlen($name.': '.$value) > 78) {
927
+				// ASCII: check if header line isn't too long and use folding
928
+				$value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value);
929
+				$tmp = wordwrap($name.': '.$value, 78, $eol . ' ');
930
+				$value = preg_replace('/^'.$name.':\s*/', '', $tmp);
931
+				// hard limit 998 (RFC2822)
932
+				$value = wordwrap($value, 998, $eol . ' ', true);
933
+			}
934
+		}
935
+
936
+		return $value;
937
+	}
938
+
939
+	/**
940
+	 * Explode quoted string
941
+	 *
942
+	 * @param string $delimiter Delimiter expression string for preg_match()
943
+	 * @param string $string    Input string
944
+	 *
945
+	 * @return array            String tokens array
946
+	 * @access private
947
+	 */
948
+	function _explodeQuotedString($delimiter, $string)
949
+	{
950
+		$result = array();
951
+		$strlen = strlen($string);
952
+
953
+		for ($q=$p=$i=0; $i < $strlen; $i++) {
954
+			if ($string[$i] == "\""
955
+				&& (empty($string[$i-1]) || $string[$i-1] != "\\")
956
+			) {
957
+				$q = $q ? false : true;
958
+			} else if (!$q && preg_match("/$delimiter/", $string[$i])) {
959
+				$result[] = substr($string, $p, $i - $p);
960
+				$p = $i + 1;
961
+			}
962
+		}
963
+
964
+		$result[] = substr($string, $p);
965
+		return $result;
966
+	}
967
+
968
+	/**
969
+	 * Encodes a header value as per RFC2047
970
+	 *
971
+	 * @param string $value      The header data to encode
972
+	 * @param string $charset    Character set name
973
+	 * @param string $encoding   Encoding name (base64 or quoted-printable)
974
+	 * @param int    $prefix_len Prefix length. Default: 0
975
+	 * @param string $eol        End-of-line sequence. Default: "\r\n"
976
+	 *
977
+	 * @return string            Encoded header data
978
+	 * @access public
979
+	 * @since 1.6.1
980
+	 */
981
+	function encodeHeaderValue($value, $charset, $encoding, $prefix_len=0, $eol="\r\n")
982
+	{
983
+		// #17311: Use multibyte aware method (requires mbstring extension)
984
+		if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) {
985
+			return $result;
986
+		}
987
+
988
+		// Generate the header using the specified params and dynamicly
989
+		// determine the maximum length of such strings.
990
+		// 75 is the value specified in the RFC.
991
+		$encoding = $encoding == 'base64' ? 'B' : 'Q';
992
+		$prefix = '=?' . $charset . '?' . $encoding .'?';
993
+		$suffix = '?=';
994
+		$maxLength = 75 - strlen($prefix . $suffix);
995
+		$maxLength1stLine = $maxLength - $prefix_len;
996
+
997
+		if ($encoding == 'B') {
998
+			// Base64 encode the entire string
999
+			$value = base64_encode($value);
1000
+
1001
+			// We can cut base64 every 4 characters, so the real max
1002
+			// we can get must be rounded down.
1003
+			$maxLength = $maxLength - ($maxLength % 4);
1004
+			$maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4);
1005
+
1006
+			$cutpoint = $maxLength1stLine;
1007
+			$output = '';
1008
+
1009
+			while ($value) {
1010
+				// Split translated string at every $maxLength
1011
+				$part = substr($value, 0, $cutpoint);
1012
+				$value = substr($value, $cutpoint);
1013
+				$cutpoint = $maxLength;
1014
+				// RFC 2047 specifies that any split header should
1015
+				// be separated by a CRLF SPACE.
1016
+				if ($output) {
1017
+					$output .= $eol . ' ';
1018
+				}
1019
+				$output .= $prefix . $part . $suffix;
1020
+			}
1021
+			$value = $output;
1022
+		} else {
1023
+			// quoted-printable encoding has been selected
1024
+			$value = Mail_mimePart::encodeQP($value);
1025
+
1026
+			// This regexp will break QP-encoded text at every $maxLength
1027
+			// but will not break any encoded letters.
1028
+			$reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|";
1029
+			$reg2nd = "|(.{0,$maxLength}[^\=][^\=])|";
1030
+
1031
+			if (strlen($value) > $maxLength1stLine) {
1032
+				// Begin with the regexp for the first line.
1033
+				$reg = $reg1st;
1034
+				$output = '';
1035
+				while ($value) {
1036
+					// Split translated string at every $maxLength
1037
+					// But make sure not to break any translated chars.
1038
+					$found = preg_match($reg, $value, $matches);
1039
+
1040
+					// After this first line, we need to use a different
1041
+					// regexp for the first line.
1042
+					$reg = $reg2nd;
1043
+
1044
+					// Save the found part and encapsulate it in the
1045
+					// prefix & suffix. Then remove the part from the
1046
+					// $value_out variable.
1047
+					if ($found) {
1048
+						$part = $matches[0];
1049
+						$len = strlen($matches[0]);
1050
+						$value = substr($value, $len);
1051
+					} else {
1052
+						$part = $value;
1053
+						$value = '';
1054
+					}
1055
+
1056
+					// RFC 2047 specifies that any split header should
1057
+					// be separated by a CRLF SPACE
1058
+					if ($output) {
1059
+						$output .= $eol . ' ';
1060
+					}
1061
+					$output .= $prefix . $part . $suffix;
1062
+				}
1063
+				$value = $output;
1064
+			} else {
1065
+				$value = $prefix . $value . $suffix;
1066
+			}
1067
+		}
1068
+
1069
+		return $value;
1070
+	}
1071
+
1072
+	/**
1073
+	 * Encodes the given string using quoted-printable
1074
+	 *
1075
+	 * @param string $str String to encode
1076
+	 *
1077
+	 * @return string     Encoded string
1078
+	 * @access public
1079
+	 * @since 1.6.0
1080
+	 */
1081
+	function encodeQP($str)
1082
+	{
1083
+		// Bug #17226 RFC 2047 restricts some characters
1084
+		// if the word is inside a phrase, permitted chars are only:
1085
+		// ASCII letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
1086
+
1087
+		// "=",  "_",  "?" must be encoded
1088
+		$regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
1089
+		$str = preg_replace_callback(
1090
+			$regexp, array('Mail_mimePart', '_qpReplaceCallback'), $str
1091
+		);
1092
+
1093
+		return str_replace(' ', '_', $str);
1094
+	}
1095
+
1096
+	/**
1097
+	 * Encodes the given string using base64 or quoted-printable.
1098
+	 * This method makes sure that encoded-word represents an integral
1099
+	 * number of characters as per RFC2047.
1100
+	 *
1101
+	 * @param string $str        String to encode
1102
+	 * @param string $charset    Character set name
1103
+	 * @param string $encoding   Encoding name (base64 or quoted-printable)
1104
+	 * @param int    $prefix_len Prefix length. Default: 0
1105
+	 * @param string $eol        End-of-line sequence. Default: "\r\n"
1106
+	 *
1107
+	 * @return string     Encoded string
1108
+	 * @access public
1109
+	 * @since 1.8.0
1110
+	 */
1111
+	function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n")
1112
+	{
1113
+		if (!function_exists('mb_substr') || !function_exists('mb_strlen')) {
1114
+			return;
1115
+		}
1116
+
1117
+		$encoding = $encoding == 'base64' ? 'B' : 'Q';
1118
+		// 75 is the value specified in the RFC
1119
+		$prefix = '=?' . $charset . '?'.$encoding.'?';
1120
+		$suffix = '?=';
1121
+		$maxLength = 75 - strlen($prefix . $suffix);
1122
+
1123
+		// A multi-octet character may not be split across adjacent encoded-words
1124
+		// So, we'll loop over each character
1125
+		// mb_stlen() with wrong charset will generate a warning here and return null
1126
+		$length      = mb_strlen($str, $charset);
1127
+		$result      = '';
1128
+		$line_length = $prefix_len;
1129
+
1130
+		if ($encoding == 'B') {
1131
+			// base64
1132
+			$start = 0;
1133
+			$prev  = '';
1134
+
1135
+			for ($i=1; $i<=$length; $i++) {
1136
+				// See #17311
1137
+				$chunk = mb_substr($str, $start, $i-$start, $charset);
1138
+				$chunk = base64_encode($chunk);
1139
+				$chunk_len = strlen($chunk);
1140
+
1141
+				if ($line_length + $chunk_len == $maxLength || $i == $length) {
1142
+					if ($result) {
1143
+						$result .= "\n";
1144
+					}
1145
+					$result .= $chunk;
1146
+					$line_length = 0;
1147
+					$start = $i;
1148
+				} else if ($line_length + $chunk_len > $maxLength) {
1149
+					if ($result) {
1150
+						$result .= "\n";
1151
+					}
1152
+					if ($prev) {
1153
+						$result .= $prev;
1154
+					}
1155
+					$line_length = 0;
1156
+					$start = $i - 1;
1157
+				} else {
1158
+					$prev = $chunk;
1159
+				}
1160
+			}
1161
+		} else {
1162
+			// quoted-printable
1163
+			// see encodeQP()
1164
+			$regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
1165
+
1166
+			for ($i=0; $i<=$length; $i++) {
1167
+				$char = mb_substr($str, $i, 1, $charset);
1168
+				// RFC recommends underline (instead of =20) in place of the space
1169
+				// that's one of the reasons why we're not using iconv_mime_encode()
1170
+				if ($char == ' ') {
1171
+					$char = '_';
1172
+					$char_len = 1;
1173
+				} else {
1174
+					$char = preg_replace_callback(
1175
+						$regexp, array('Mail_mimePart', '_qpReplaceCallback'), $char
1176
+					);
1177
+					$char_len = strlen($char);
1178
+				}
1179
+
1180
+				if ($line_length + $char_len > $maxLength) {
1181
+					if ($result) {
1182
+						$result .= "\n";
1183
+					}
1184
+					$line_length = 0;
1185
+				}
1186
+
1187
+				$result      .= $char;
1188
+				$line_length += $char_len;
1189
+			}
1190
+		}
1191
+
1192
+		if ($result) {
1193
+			$result = $prefix
1194
+				.str_replace("\n", $suffix.$eol.' '.$prefix, $result).$suffix;
1195
+		}
1196
+
1197
+		return $result;
1198
+	}
1199
+
1200
+	/**
1201
+	 * Callback function to replace extended characters (\x80-xFF) with their
1202
+	 * ASCII values (RFC2047: quoted-printable)
1203
+	 *
1204
+	 * @param array $matches Preg_replace's matches array
1205
+	 *
1206
+	 * @return string        Encoded character string
1207
+	 * @access private
1208
+	 */
1209
+	function _qpReplaceCallback($matches)
1210
+	{
1211
+		return sprintf('=%02X', ord($matches[1]));
1212
+	}
1213
+
1214
+	/**
1215
+	 * Callback function to replace extended characters (\x80-xFF) with their
1216
+	 * ASCII values (RFC2231)
1217
+	 *
1218
+	 * @param array $matches Preg_replace's matches array
1219
+	 *
1220
+	 * @return string        Encoded character string
1221
+	 * @access private
1222
+	 */
1223
+	function _encodeReplaceCallback($matches)
1224
+	{
1225
+		return sprintf('%%%02X', ord($matches[1]));
1226
+	}
1227
+
1228
+	/**
1229
+	 * PEAR::isError implementation
1230
+	 *
1231
+	 * @param mixed $data Object
1232
+	 *
1233
+	 * @return bool True if object is an instance of PEAR_Error
1234
+	 * @access private
1235
+	 */
1236
+	function _isError($data)
1237
+	{
1238
+		// PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
1239
+		if (is_object($data) && is_a($data, 'PEAR_Error')) {
1240
+			return true;
1241
+		}
1242
+
1243
+		return false;
1244
+	}
1245
+
1246
+	/**
1247
+	 * PEAR::raiseError implementation
1248
+	 *
1249
+	 * @param $message A text error message
1250
+	 *
1251
+	 * @return PEAR_Error Instance of PEAR_Error
1252
+	 * @access private
1253
+	 */
1254
+	function _raiseError($message)
1255
+	{
1256
+		// PEAR::raiseError() is not PHP 5.4 compatible
1257
+		return new PEAR_Error($message);
1258
+	}
1259 1259
 
1260 1260
 } // End of class
Please login to merge, or discard this patch.
htdocs/includes/nusoap/lib/Mail/mime.php 1 patch
Indentation   +1378 added lines, -1378 removed lines patch added patch discarded remove patch
@@ -94,852 +94,852 @@  discard block
 block discarded – undo
94 94
  */
95 95
 class Mail_mime
96 96
 {
97
-    /**
98
-     * Contains the plain text part of the email
99
-     *
100
-     * @var string
101
-     * @access private
102
-     */
103
-    var $_txtbody;
104
-
105
-    /**
106
-     * Contains the html part of the email
107
-     *
108
-     * @var string
109
-     * @access private
110
-     */
111
-    var $_htmlbody;
112
-
113
-    /**
114
-     * list of the attached images
115
-     *
116
-     * @var array
117
-     * @access private
118
-     */
119
-    var $_html_images = array();
120
-
121
-    /**
122
-     * list of the attachements
123
-     *
124
-     * @var array
125
-     * @access private
126
-     */
127
-    var $_parts = array();
128
-
129
-    /**
130
-     * Headers for the mail
131
-     *
132
-     * @var array
133
-     * @access private
134
-     */
135
-    var $_headers = array();
136
-
137
-    /**
138
-     * Build parameters
139
-     *
140
-     * @var array
141
-     * @access private
142
-     */
143
-    var $_build_params = array(
144
-        // What encoding to use for the headers
145
-        // Options: quoted-printable or base64
146
-        'head_encoding' => 'quoted-printable',
147
-        // What encoding to use for plain text
148
-        // Options: 7bit, 8bit, base64, or quoted-printable
149
-        'text_encoding' => 'quoted-printable',
150
-        // What encoding to use for html
151
-        // Options: 7bit, 8bit, base64, or quoted-printable
152
-        'html_encoding' => 'quoted-printable',
153
-        // The character set to use for html
154
-        'html_charset'  => 'ISO-8859-1',
155
-        // The character set to use for text
156
-        'text_charset'  => 'ISO-8859-1',
157
-        // The character set to use for headers
158
-        'head_charset'  => 'ISO-8859-1',
159
-        // End-of-line sequence
160
-        'eol'           => "\r\n",
161
-        // Delay attachment files IO until building the message
162
-        'delay_file_io' => false
163
-    );
164
-
165
-    /**
166
-     * Constructor function
167
-     *
168
-     * @param mixed $params Build parameters that change the way the email
169
-     *                      is built. Should be an associative array.
170
-     *                      See $_build_params.
171
-     *
172
-     * @return void
173
-     * @access public
174
-     */
175
-    function Mail_mime($params = array())
176
-    {
177
-        // Backward-compatible EOL setting
178
-        if (is_string($params)) {
179
-            $this->_build_params['eol'] = $params;
180
-        } else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) {
181
-            $this->_build_params['eol'] = MAIL_MIME_CRLF;
182
-        }
183
-
184
-        // Update build parameters
185
-        if (!empty($params) && is_array($params)) {
186
-            while (list($key, $value) = each($params)) {
187
-                $this->_build_params[$key] = $value;
188
-            }
189
-        }
190
-    }
191
-
192
-    /**
193
-     * Set build parameter value
194
-     *
195
-     * @param string $name  Parameter name
196
-     * @param string $value Parameter value
197
-     *
198
-     * @return void
199
-     * @access public
200
-     * @since 1.6.0
201
-     */
202
-    function setParam($name, $value)
203
-    {
204
-        $this->_build_params[$name] = $value;
205
-    }
206
-
207
-    /**
208
-     * Get build parameter value
209
-     *
210
-     * @param string $name Parameter name
211
-     *
212
-     * @return mixed Parameter value
213
-     * @access public
214
-     * @since 1.6.0
215
-     */
216
-    function getParam($name)
217
-    {
218
-        return isset($this->_build_params[$name]) ? $this->_build_params[$name] : null;
219
-    }
220
-
221
-    /**
222
-     * Accessor function to set the body text. Body text is used if
223
-     * it's not an html mail being sent or else is used to fill the
224
-     * text/plain part that emails clients who don't support
225
-     * html should show.
226
-     *
227
-     * @param string $data   Either a string or
228
-     *                       the file name with the contents
229
-     * @param bool   $isfile If true the first param should be treated
230
-     *                       as a file name, else as a string (default)
231
-     * @param bool   $append If true the text or file is appended to
232
-     *                       the existing body, else the old body is
233
-     *                       overwritten
234
-     *
235
-     * @return mixed         True on success or PEAR_Error object
236
-     * @access public
237
-     */
238
-    function setTXTBody($data, $isfile = false, $append = false)
239
-    {
240
-        if (!$isfile) {
241
-            if (!$append) {
242
-                $this->_txtbody = $data;
243
-            } else {
244
-                $this->_txtbody .= $data;
245
-            }
246
-        } else {
247
-            $cont = $this->_file2str($data);
248
-            if ($this->_isError($cont)) {
249
-                return $cont;
250
-            }
251
-            if (!$append) {
252
-                $this->_txtbody = $cont;
253
-            } else {
254
-                $this->_txtbody .= $cont;
255
-            }
256
-        }
257
-
258
-        return true;
259
-    }
260
-
261
-    /**
262
-     * Get message text body
263
-     *
264
-     * @return string Text body
265
-     * @access public
266
-     * @since 1.6.0
267
-     */
268
-    function getTXTBody()
269
-    {
270
-        return $this->_txtbody;
271
-    }
272
-
273
-    /**
274
-     * Adds a html part to the mail.
275
-     *
276
-     * @param string $data   Either a string or the file name with the
277
-     *                       contents
278
-     * @param bool   $isfile A flag that determines whether $data is a
279
-     *                       filename, or a string(false, default)
280
-     *
281
-     * @return bool          True on success
282
-     * @access public
283
-     */
284
-    function setHTMLBody($data, $isfile = false)
285
-    {
286
-        if (!$isfile) {
287
-            $this->_htmlbody = $data;
288
-        } else {
289
-            $cont = $this->_file2str($data);
290
-            if ($this->_isError($cont)) {
291
-                return $cont;
292
-            }
293
-            $this->_htmlbody = $cont;
294
-        }
295
-
296
-        return true;
297
-    }
298
-
299
-    /**
300
-     * Get message HTML body
301
-     *
302
-     * @return string HTML body
303
-     * @access public
304
-     * @since 1.6.0
305
-     */
306
-    function getHTMLBody()
307
-    {
308
-        return $this->_htmlbody;
309
-    }
310
-
311
-    /**
312
-     * Adds an image to the list of embedded images.
313
-     *
314
-     * @param string $file       The image file name OR image data itself
315
-     * @param string $c_type     The content type
316
-     * @param string $name       The filename of the image.
317
-     *                           Only used if $file is the image data.
318
-     * @param bool   $isfile     Whether $file is a filename or not.
319
-     *                           Defaults to true
320
-     * @param string $content_id Desired Content-ID of MIME part
321
-     *                           Defaults to generated unique ID
322
-     *
323
-     * @return bool          True on success
324
-     * @access public
325
-     */
326
-    function addHTMLImage($file,
327
-        $c_type='application/octet-stream',
328
-        $name = '',
329
-        $isfile = true,
330
-        $content_id = null
331
-    ) {
332
-        $bodyfile = null;
333
-
334
-        if ($isfile) {
335
-            // Don't load file into memory
336
-            if ($this->_build_params['delay_file_io']) {
337
-                $filedata = null;
338
-                $bodyfile = $file;
339
-            } else {
340
-                if ($this->_isError($filedata = $this->_file2str($file))) {
341
-                    return $filedata;
342
-                }
343
-            }
344
-            $filename = ($name ? $name : $file);
345
-        } else {
346
-            $filedata = $file;
347
-            $filename = $name;
348
-        }
349
-
350
-        if (!$content_id) {
351
-            $content_id = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true));
352
-        }
353
-
354
-        $this->_html_images[] = array(
355
-            'body'      => $filedata,
356
-            'body_file' => $bodyfile,
357
-            'name'      => $filename,
358
-            'c_type'    => $c_type,
359
-            'cid'       => $content_id
360
-        );
361
-
362
-        return true;
363
-    }
364
-
365
-    /**
366
-     * Adds a file to the list of attachments.
367
-     *
368
-     * @param string $file        The file name of the file to attach
369
-     *                            or the file contents itself
370
-     * @param string $c_type      The content type
371
-     * @param string $name        The filename of the attachment
372
-     *                            Only use if $file is the contents
373
-     * @param bool   $isfile      Whether $file is a filename or not. Defaults to true
374
-     * @param string $encoding    The type of encoding to use. Defaults to base64.
375
-     *                            Possible values: 7bit, 8bit, base64 or quoted-printable.
376
-     * @param string $disposition The content-disposition of this file
377
-     *                            Defaults to attachment.
378
-     *                            Possible values: attachment, inline.
379
-     * @param string $charset     The character set of attachment's content.
380
-     * @param string $language    The language of the attachment
381
-     * @param string $location    The RFC 2557.4 location of the attachment
382
-     * @param string $n_encoding  Encoding of the attachment's name in Content-Type
383
-     *                            By default filenames are encoded using RFC2231 method
384
-     *                            Here you can set RFC2047 encoding (quoted-printable
385
-     *                            or base64) instead
386
-     * @param string $f_encoding  Encoding of the attachment's filename
387
-     *                            in Content-Disposition header.
388
-     * @param string $description Content-Description header
389
-     * @param string $h_charset   The character set of the headers e.g. filename
390
-     *                            If not specified, $charset will be used
391
-     * @param array  $add_headers Additional part headers. Array keys can be in form
392
-     *                            of <header_name>:<parameter_name>
393
-     *
394
-     * @return mixed              True on success or PEAR_Error object
395
-     * @access public
396
-     */
397
-    function addAttachment($file,
398
-        $c_type      = 'application/octet-stream',
399
-        $name        = '',
400
-        $isfile      = true,
401
-        $encoding    = 'base64',
402
-        $disposition = 'attachment',
403
-        $charset     = '',
404
-        $language    = '',
405
-        $location    = '',
406
-        $n_encoding  = null,
407
-        $f_encoding  = null,
408
-        $description = '',
409
-        $h_charset   = null,
410
-        $add_headers = array()
411
-    ) {
412
-        $bodyfile = null;
413
-
414
-        if ($isfile) {
415
-            // Don't load file into memory
416
-            if ($this->_build_params['delay_file_io']) {
417
-                $filedata = null;
418
-                $bodyfile = $file;
419
-            } else {
420
-                if ($this->_isError($filedata = $this->_file2str($file))) {
421
-                    return $filedata;
422
-                }
423
-            }
424
-            // Force the name the user supplied, otherwise use $file
425
-            $filename = ($name ? $name : $this->_basename($file));
426
-        } else {
427
-            $filedata = $file;
428
-            $filename = $name;
429
-        }
430
-
431
-        if (!strlen($filename)) {
432
-            $msg = "The supplied filename for the attachment can't be empty";
433
-            return $this->_raiseError($msg);
434
-        }
435
-
436
-        $this->_parts[] = array(
437
-            'body'        => $filedata,
438
-            'body_file'   => $bodyfile,
439
-            'name'        => $filename,
440
-            'c_type'      => $c_type,
441
-            'charset'     => $charset,
442
-            'encoding'    => $encoding,
443
-            'language'    => $language,
444
-            'location'    => $location,
445
-            'disposition' => $disposition,
446
-            'description' => $description,
447
-            'add_headers' => $add_headers,
448
-            'name_encoding'     => $n_encoding,
449
-            'filename_encoding' => $f_encoding,
450
-            'headers_charset'   => $h_charset,
451
-        );
452
-
453
-        return true;
454
-    }
455
-
456
-    /**
457
-     * Get the contents of the given file name as string
458
-     *
459
-     * @param string $file_name Path of file to process
460
-     *
461
-     * @return string           Contents of $file_name
462
-     * @access private
463
-     */
464
-    function _file2str($file_name)
465
-    {
466
-        // Check state of file and raise an error properly
467
-        if (!file_exists($file_name)) {
468
-            return $this->_raiseError('File not found: ' . $file_name);
469
-        }
470
-        if (!is_file($file_name)) {
471
-            return $this->_raiseError('Not a regular file: ' . $file_name);
472
-        }
473
-        if (!is_readable($file_name)) {
474
-            return $this->_raiseError('File is not readable: ' . $file_name);
475
-        }
476
-
477
-        // Temporarily reset magic_quotes_runtime and read file contents
478
-        if ($magic_quote_setting = get_magic_quotes_runtime()) {
479
-            @ini_set('magic_quotes_runtime', 0);
480
-        }
481
-        $cont = file_get_contents($file_name);
482
-        if ($magic_quote_setting) {
483
-            @ini_set('magic_quotes_runtime', $magic_quote_setting);
484
-        }
485
-
486
-        return $cont;
487
-    }
488
-
489
-    /**
490
-     * Adds a text subpart to the mimePart object and
491
-     * returns it during the build process.
492
-     *
493
-     * @param mixed  &$obj The object to add the part to, or
494
-     *                     anything else if a new object is to be created.
495
-     * @param string $text The text to add.
496
-     *
497
-     * @return object      The text mimePart object
498
-     * @access private
499
-     */
500
-    function &_addTextPart(&$obj, $text = '')
501
-    {
502
-        $params['content_type'] = 'text/plain';
503
-        $params['encoding']     = $this->_build_params['text_encoding'];
504
-        $params['charset']      = $this->_build_params['text_charset'];
505
-        $params['eol']          = $this->_build_params['eol'];
506
-
507
-        if (is_object($obj)) {
508
-            $ret = $obj->addSubpart($text, $params);
509
-        } else {
510
-            $ret = new Mail_mimePart($text, $params);
511
-        }
512
-
513
-        return $ret;
514
-    }
515
-
516
-    /**
517
-     * Adds a html subpart to the mimePart object and
518
-     * returns it during the build process.
519
-     *
520
-     * @param mixed &$obj The object to add the part to, or
521
-     *                    anything else if a new object is to be created.
522
-     *
523
-     * @return object     The html mimePart object
524
-     * @access private
525
-     */
526
-    function &_addHtmlPart(&$obj)
527
-    {
528
-        $params['content_type'] = 'text/html';
529
-        $params['encoding']     = $this->_build_params['html_encoding'];
530
-        $params['charset']      = $this->_build_params['html_charset'];
531
-        $params['eol']          = $this->_build_params['eol'];
532
-
533
-        if (is_object($obj)) {
534
-            $ret = $obj->addSubpart($this->_htmlbody, $params);
535
-        } else {
536
-            $ret = new Mail_mimePart($this->_htmlbody, $params);
537
-        }
538
-
539
-        return $ret;
540
-    }
541
-
542
-    /**
543
-     * Creates a new mimePart object, using multipart/mixed as
544
-     * the initial content-type and returns it during the
545
-     * build process.
546
-     *
547
-     * @return object The multipart/mixed mimePart object
548
-     * @access private
549
-     */
550
-    function &_addMixedPart()
551
-    {
552
-        $params['content_type'] = 'multipart/mixed';
553
-        $params['eol']          = $this->_build_params['eol'];
554
-
555
-        // Create empty multipart/mixed Mail_mimePart object to return
556
-        $ret = new Mail_mimePart('', $params);
557
-        return $ret;
558
-    }
559
-
560
-    /**
561
-     * Adds a multipart/alternative part to a mimePart
562
-     * object (or creates one), and returns it during
563
-     * the build process.
564
-     *
565
-     * @param mixed &$obj The object to add the part to, or
566
-     *                    anything else if a new object is to be created.
567
-     *
568
-     * @return object     The multipart/mixed mimePart object
569
-     * @access private
570
-     */
571
-    function &_addAlternativePart(&$obj)
572
-    {
573
-        $params['content_type'] = 'multipart/alternative';
574
-        $params['eol']          = $this->_build_params['eol'];
575
-
576
-        if (is_object($obj)) {
577
-            $ret = $obj->addSubpart('', $params);
578
-        } else {
579
-            $ret = new Mail_mimePart('', $params);
580
-        }
581
-
582
-        return $ret;
583
-    }
584
-
585
-    /**
586
-     * Adds a multipart/related part to a mimePart
587
-     * object (or creates one), and returns it during
588
-     * the build process.
589
-     *
590
-     * @param mixed &$obj The object to add the part to, or
591
-     *                    anything else if a new object is to be created
592
-     *
593
-     * @return object     The multipart/mixed mimePart object
594
-     * @access private
595
-     */
596
-    function &_addRelatedPart(&$obj)
597
-    {
598
-        $params['content_type'] = 'multipart/related';
599
-        $params['eol']          = $this->_build_params['eol'];
600
-
601
-        if (is_object($obj)) {
602
-            $ret = $obj->addSubpart('', $params);
603
-        } else {
604
-            $ret = new Mail_mimePart('', $params);
605
-        }
606
-
607
-        return $ret;
608
-    }
609
-
610
-    /**
611
-     * Adds an html image subpart to a mimePart object
612
-     * and returns it during the build process.
613
-     *
614
-     * @param object &$obj  The mimePart to add the image to
615
-     * @param array  $value The image information
616
-     *
617
-     * @return object       The image mimePart object
618
-     * @access private
619
-     */
620
-    function &_addHtmlImagePart(&$obj, $value)
621
-    {
622
-        $params['content_type'] = $value['c_type'];
623
-        $params['encoding']     = 'base64';
624
-        $params['disposition']  = 'inline';
625
-        $params['filename']     = $value['name'];
626
-        $params['cid']          = $value['cid'];
627
-        $params['body_file']    = $value['body_file'];
628
-        $params['eol']          = $this->_build_params['eol'];
629
-
630
-        if (!empty($value['name_encoding'])) {
631
-            $params['name_encoding'] = $value['name_encoding'];
632
-        }
633
-        if (!empty($value['filename_encoding'])) {
634
-            $params['filename_encoding'] = $value['filename_encoding'];
635
-        }
636
-
637
-        $ret = $obj->addSubpart($value['body'], $params);
638
-        return $ret;
639
-    }
640
-
641
-    /**
642
-     * Adds an attachment subpart to a mimePart object
643
-     * and returns it during the build process.
644
-     *
645
-     * @param object &$obj  The mimePart to add the image to
646
-     * @param array  $value The attachment information
647
-     *
648
-     * @return object       The image mimePart object
649
-     * @access private
650
-     */
651
-    function &_addAttachmentPart(&$obj, $value)
652
-    {
653
-        $params['eol']          = $this->_build_params['eol'];
654
-        $params['filename']     = $value['name'];
655
-        $params['encoding']     = $value['encoding'];
656
-        $params['content_type'] = $value['c_type'];
657
-        $params['body_file']    = $value['body_file'];
658
-        $params['disposition']  = isset($value['disposition']) ? 
659
-                                  $value['disposition'] : 'attachment';
660
-
661
-        // content charset
662
-        if (!empty($value['charset'])) {
663
-            $params['charset'] = $value['charset'];
664
-        }
665
-        // headers charset (filename, description)
666
-        if (!empty($value['headers_charset'])) {
667
-            $params['headers_charset'] = $value['headers_charset'];
668
-        }
669
-        if (!empty($value['language'])) {
670
-            $params['language'] = $value['language'];
671
-        }
672
-        if (!empty($value['location'])) {
673
-            $params['location'] = $value['location'];
674
-        }
675
-        if (!empty($value['name_encoding'])) {
676
-            $params['name_encoding'] = $value['name_encoding'];
677
-        }
678
-        if (!empty($value['filename_encoding'])) {
679
-            $params['filename_encoding'] = $value['filename_encoding'];
680
-        }
681
-        if (!empty($value['description'])) {
682
-            $params['description'] = $value['description'];
683
-        }
684
-        if (is_array($value['add_headers'])) {
685
-            $params['headers'] = $value['add_headers'];
686
-        }
687
-
688
-        $ret = $obj->addSubpart($value['body'], $params);
689
-        return $ret;
690
-    }
691
-
692
-    /**
693
-     * Returns the complete e-mail, ready to send using an alternative
694
-     * mail delivery method. Note that only the mailpart that is made
695
-     * with Mail_Mime is created. This means that,
696
-     * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF 
697
-     * using the $headers parameter!
698
-     * 
699
-     * @param string $separation The separation between these two parts.
700
-     * @param array  $params     The Build parameters passed to the
701
-     *                           get() function. See get() for more info.
702
-     * @param array  $headers    The extra headers that should be passed
703
-     *                           to the headers() method.
704
-     *                           See that function for more info.
705
-     * @param bool   $overwrite  Overwrite the existing headers with new.
706
-     *
707
-     * @return mixed The complete e-mail or PEAR error object
708
-     * @access public
709
-     */
710
-    function getMessage($separation = null, $params = null, $headers = null,
711
-        $overwrite = false
712
-    ) {
713
-        if ($separation === null) {
714
-            $separation = $this->_build_params['eol'];
715
-        }
716
-
717
-        $body = $this->get($params);
718
-
719
-        if ($this->_isError($body)) {
720
-            return $body;
721
-        }
722
-
723
-        return $this->txtHeaders($headers, $overwrite) . $separation . $body;
724
-    }
725
-
726
-    /**
727
-     * Returns the complete e-mail body, ready to send using an alternative
728
-     * mail delivery method.
729
-     * 
730
-     * @param array $params The Build parameters passed to the
731
-     *                      get() method. See get() for more info.
732
-     *
733
-     * @return mixed The e-mail body or PEAR error object
734
-     * @access public
735
-     * @since 1.6.0
736
-     */
737
-    function getMessageBody($params = null)
738
-    {
739
-        return $this->get($params, null, true);
740
-    }
741
-
742
-    /**
743
-     * Writes (appends) the complete e-mail into file.
744
-     * 
745
-     * @param string $filename  Output file location
746
-     * @param array  $params    The Build parameters passed to the
747
-     *                          get() method. See get() for more info.
748
-     * @param array  $headers   The extra headers that should be passed
749
-     *                          to the headers() function.
750
-     *                          See that function for more info.
751
-     * @param bool   $overwrite Overwrite the existing headers with new.
752
-     *
753
-     * @return mixed True or PEAR error object
754
-     * @access public
755
-     * @since 1.6.0
756
-     */
757
-    function saveMessage($filename, $params = null, $headers = null, $overwrite = false)
758
-    {
759
-        // Check state of file and raise an error properly
760
-        if (file_exists($filename) && !is_writable($filename)) {
761
-            return $this->_raiseError('File is not writable: ' . $filename);
762
-        }
763
-
764
-        // Temporarily reset magic_quotes_runtime and read file contents
765
-        if ($magic_quote_setting = get_magic_quotes_runtime()) {
766
-            @ini_set('magic_quotes_runtime', 0);
767
-        }
768
-
769
-        if (!($fh = fopen($filename, 'ab'))) {
770
-            return $this->_raiseError('Unable to open file: ' . $filename);
771
-        }
772
-
773
-        // Write message headers into file (skipping Content-* headers)
774
-        $head = $this->txtHeaders($headers, $overwrite, true);
775
-        if (fwrite($fh, $head) === false) {
776
-            return $this->_raiseError('Error writing to file: ' . $filename);
777
-        }
778
-
779
-        fclose($fh);
780
-
781
-        if ($magic_quote_setting) {
782
-            @ini_set('magic_quotes_runtime', $magic_quote_setting);
783
-        }
784
-
785
-        // Write the rest of the message into file
786
-        $res = $this->get($params, $filename);
787
-
788
-        return $res ? $res : true;
789
-    }
790
-
791
-    /**
792
-     * Writes (appends) the complete e-mail body into file.
793
-     *
794
-     * @param string $filename Output file location
795
-     * @param array  $params   The Build parameters passed to the
796
-     *                         get() method. See get() for more info.
797
-     *
798
-     * @return mixed True or PEAR error object
799
-     * @access public
800
-     * @since 1.6.0
801
-     */
802
-    function saveMessageBody($filename, $params = null)
803
-    {
804
-        // Check state of file and raise an error properly
805
-        if (file_exists($filename) && !is_writable($filename)) {
806
-            return $this->_raiseError('File is not writable: ' . $filename);
807
-        }
808
-
809
-        // Temporarily reset magic_quotes_runtime and read file contents
810
-        if ($magic_quote_setting = get_magic_quotes_runtime()) {
811
-            @ini_set('magic_quotes_runtime', 0);
812
-        }
813
-
814
-        if (!($fh = fopen($filename, 'ab'))) {
815
-            return $this->_raiseError('Unable to open file: ' . $filename);
816
-        }
817
-
818
-        // Write the rest of the message into file
819
-        $res = $this->get($params, $filename, true);
820
-
821
-        return $res ? $res : true;
822
-    }
823
-
824
-    /**
825
-     * Builds the multipart message from the list ($this->_parts) and
826
-     * returns the mime content.
827
-     *
828
-     * @param array    $params    Build parameters that change the way the email
829
-     *                            is built. Should be associative. See $_build_params.
830
-     * @param resource $filename  Output file where to save the message instead of
831
-     *                            returning it
832
-     * @param boolean  $skip_head True if you want to return/save only the message
833
-     *                            without headers
834
-     *
835
-     * @return mixed The MIME message content string, null or PEAR error object
836
-     * @access public
837
-     */
838
-    function get($params = null, $filename = null, $skip_head = false)
839
-    {
840
-        if (isset($params)) {
841
-            while (list($key, $value) = each($params)) {
842
-                $this->_build_params[$key] = $value;
843
-            }
844
-        }
845
-
846
-        if (isset($this->_headers['From'])) {
847
-            // Bug #11381: Illegal characters in domain ID
848
-            if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->_headers['From'], $matches)) {
849
-                $domainID = $matches[1];
850
-            } else {
851
-                $domainID = '@localhost';
852
-            }
853
-            foreach ($this->_html_images as $i => $img) {
854
-                $cid = $this->_html_images[$i]['cid']; 
855
-                if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) {
856
-                    $this->_html_images[$i]['cid'] = $cid . $domainID;
857
-                }
858
-            }
859
-        }
860
-
861
-        if (count($this->_html_images) && isset($this->_htmlbody)) {
862
-            foreach ($this->_html_images as $key => $value) {
863
-                $regex   = array();
864
-                $regex[] = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' .
865
-                            preg_quote($value['name'], '#') . '\3#';
866
-                $regex[] = '#(?i)url(?-i)\(\s*(["\']?)' .
867
-                            preg_quote($value['name'], '#') . '\1\s*\)#';
868
-
869
-                $rep   = array();
870
-                $rep[] = '\1\2=\3cid:' . $value['cid'] .'\3';
871
-                $rep[] = 'url(\1cid:' . $value['cid'] . '\1)';
872
-
873
-                $this->_htmlbody = preg_replace($regex, $rep, $this->_htmlbody);
874
-                $this->_html_images[$key]['name']
875
-                    = $this->_basename($this->_html_images[$key]['name']);
876
-            }
877
-        }
878
-
879
-        $this->_checkParams();
880
-
881
-        $null        = -1;
882
-        $attachments = count($this->_parts) > 0;
883
-        $html_images = count($this->_html_images) > 0;
884
-        $html        = strlen($this->_htmlbody) > 0;
885
-        $text        = !$html && strlen($this->_txtbody);
886
-
887
-        switch (true) {
888
-        case $text && !$attachments:
889
-            $message =& $this->_addTextPart($null, $this->_txtbody);
890
-            break;
891
-
892
-        case !$text && !$html && $attachments:
893
-            $message =& $this->_addMixedPart();
894
-            for ($i = 0; $i < count($this->_parts); $i++) {
895
-                $this->_addAttachmentPart($message, $this->_parts[$i]);
896
-            }
897
-            break;
898
-
899
-        case $text && $attachments:
900
-            $message =& $this->_addMixedPart();
901
-            $this->_addTextPart($message, $this->_txtbody);
902
-            for ($i = 0; $i < count($this->_parts); $i++) {
903
-                $this->_addAttachmentPart($message, $this->_parts[$i]);
904
-            }
905
-            break;
906
-
907
-        case $html && !$attachments && !$html_images:
908
-            if (isset($this->_txtbody)) {
909
-                $message =& $this->_addAlternativePart($null);
910
-                $this->_addTextPart($message, $this->_txtbody);
911
-                $this->_addHtmlPart($message);
912
-            } else {
913
-                $message =& $this->_addHtmlPart($null);
914
-            }
915
-            break;
916
-
917
-        case $html && !$attachments && $html_images:
918
-            // * Content-Type: multipart/alternative;
919
-            //    * text
920
-            //    * Content-Type: multipart/related;
921
-            //       * html
922
-            //       * image...
923
-            if (isset($this->_txtbody)) {
924
-                $message =& $this->_addAlternativePart($null);
925
-                $this->_addTextPart($message, $this->_txtbody);
926
-
927
-                $ht =& $this->_addRelatedPart($message);
928
-                $this->_addHtmlPart($ht);
929
-                for ($i = 0; $i < count($this->_html_images); $i++) {
930
-                    $this->_addHtmlImagePart($ht, $this->_html_images[$i]);
931
-                }
932
-            } else {
933
-                // * Content-Type: multipart/related;
934
-                //    * html
935
-                //    * image...
936
-                $message =& $this->_addRelatedPart($null);
937
-                $this->_addHtmlPart($message);
938
-                for ($i = 0; $i < count($this->_html_images); $i++) {
939
-                    $this->_addHtmlImagePart($message, $this->_html_images[$i]);
940
-                }
941
-            }
942
-            /*
97
+	/**
98
+	 * Contains the plain text part of the email
99
+	 *
100
+	 * @var string
101
+	 * @access private
102
+	 */
103
+	var $_txtbody;
104
+
105
+	/**
106
+	 * Contains the html part of the email
107
+	 *
108
+	 * @var string
109
+	 * @access private
110
+	 */
111
+	var $_htmlbody;
112
+
113
+	/**
114
+	 * list of the attached images
115
+	 *
116
+	 * @var array
117
+	 * @access private
118
+	 */
119
+	var $_html_images = array();
120
+
121
+	/**
122
+	 * list of the attachements
123
+	 *
124
+	 * @var array
125
+	 * @access private
126
+	 */
127
+	var $_parts = array();
128
+
129
+	/**
130
+	 * Headers for the mail
131
+	 *
132
+	 * @var array
133
+	 * @access private
134
+	 */
135
+	var $_headers = array();
136
+
137
+	/**
138
+	 * Build parameters
139
+	 *
140
+	 * @var array
141
+	 * @access private
142
+	 */
143
+	var $_build_params = array(
144
+		// What encoding to use for the headers
145
+		// Options: quoted-printable or base64
146
+		'head_encoding' => 'quoted-printable',
147
+		// What encoding to use for plain text
148
+		// Options: 7bit, 8bit, base64, or quoted-printable
149
+		'text_encoding' => 'quoted-printable',
150
+		// What encoding to use for html
151
+		// Options: 7bit, 8bit, base64, or quoted-printable
152
+		'html_encoding' => 'quoted-printable',
153
+		// The character set to use for html
154
+		'html_charset'  => 'ISO-8859-1',
155
+		// The character set to use for text
156
+		'text_charset'  => 'ISO-8859-1',
157
+		// The character set to use for headers
158
+		'head_charset'  => 'ISO-8859-1',
159
+		// End-of-line sequence
160
+		'eol'           => "\r\n",
161
+		// Delay attachment files IO until building the message
162
+		'delay_file_io' => false
163
+	);
164
+
165
+	/**
166
+	 * Constructor function
167
+	 *
168
+	 * @param mixed $params Build parameters that change the way the email
169
+	 *                      is built. Should be an associative array.
170
+	 *                      See $_build_params.
171
+	 *
172
+	 * @return void
173
+	 * @access public
174
+	 */
175
+	function Mail_mime($params = array())
176
+	{
177
+		// Backward-compatible EOL setting
178
+		if (is_string($params)) {
179
+			$this->_build_params['eol'] = $params;
180
+		} else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) {
181
+			$this->_build_params['eol'] = MAIL_MIME_CRLF;
182
+		}
183
+
184
+		// Update build parameters
185
+		if (!empty($params) && is_array($params)) {
186
+			while (list($key, $value) = each($params)) {
187
+				$this->_build_params[$key] = $value;
188
+			}
189
+		}
190
+	}
191
+
192
+	/**
193
+	 * Set build parameter value
194
+	 *
195
+	 * @param string $name  Parameter name
196
+	 * @param string $value Parameter value
197
+	 *
198
+	 * @return void
199
+	 * @access public
200
+	 * @since 1.6.0
201
+	 */
202
+	function setParam($name, $value)
203
+	{
204
+		$this->_build_params[$name] = $value;
205
+	}
206
+
207
+	/**
208
+	 * Get build parameter value
209
+	 *
210
+	 * @param string $name Parameter name
211
+	 *
212
+	 * @return mixed Parameter value
213
+	 * @access public
214
+	 * @since 1.6.0
215
+	 */
216
+	function getParam($name)
217
+	{
218
+		return isset($this->_build_params[$name]) ? $this->_build_params[$name] : null;
219
+	}
220
+
221
+	/**
222
+	 * Accessor function to set the body text. Body text is used if
223
+	 * it's not an html mail being sent or else is used to fill the
224
+	 * text/plain part that emails clients who don't support
225
+	 * html should show.
226
+	 *
227
+	 * @param string $data   Either a string or
228
+	 *                       the file name with the contents
229
+	 * @param bool   $isfile If true the first param should be treated
230
+	 *                       as a file name, else as a string (default)
231
+	 * @param bool   $append If true the text or file is appended to
232
+	 *                       the existing body, else the old body is
233
+	 *                       overwritten
234
+	 *
235
+	 * @return mixed         True on success or PEAR_Error object
236
+	 * @access public
237
+	 */
238
+	function setTXTBody($data, $isfile = false, $append = false)
239
+	{
240
+		if (!$isfile) {
241
+			if (!$append) {
242
+				$this->_txtbody = $data;
243
+			} else {
244
+				$this->_txtbody .= $data;
245
+			}
246
+		} else {
247
+			$cont = $this->_file2str($data);
248
+			if ($this->_isError($cont)) {
249
+				return $cont;
250
+			}
251
+			if (!$append) {
252
+				$this->_txtbody = $cont;
253
+			} else {
254
+				$this->_txtbody .= $cont;
255
+			}
256
+		}
257
+
258
+		return true;
259
+	}
260
+
261
+	/**
262
+	 * Get message text body
263
+	 *
264
+	 * @return string Text body
265
+	 * @access public
266
+	 * @since 1.6.0
267
+	 */
268
+	function getTXTBody()
269
+	{
270
+		return $this->_txtbody;
271
+	}
272
+
273
+	/**
274
+	 * Adds a html part to the mail.
275
+	 *
276
+	 * @param string $data   Either a string or the file name with the
277
+	 *                       contents
278
+	 * @param bool   $isfile A flag that determines whether $data is a
279
+	 *                       filename, or a string(false, default)
280
+	 *
281
+	 * @return bool          True on success
282
+	 * @access public
283
+	 */
284
+	function setHTMLBody($data, $isfile = false)
285
+	{
286
+		if (!$isfile) {
287
+			$this->_htmlbody = $data;
288
+		} else {
289
+			$cont = $this->_file2str($data);
290
+			if ($this->_isError($cont)) {
291
+				return $cont;
292
+			}
293
+			$this->_htmlbody = $cont;
294
+		}
295
+
296
+		return true;
297
+	}
298
+
299
+	/**
300
+	 * Get message HTML body
301
+	 *
302
+	 * @return string HTML body
303
+	 * @access public
304
+	 * @since 1.6.0
305
+	 */
306
+	function getHTMLBody()
307
+	{
308
+		return $this->_htmlbody;
309
+	}
310
+
311
+	/**
312
+	 * Adds an image to the list of embedded images.
313
+	 *
314
+	 * @param string $file       The image file name OR image data itself
315
+	 * @param string $c_type     The content type
316
+	 * @param string $name       The filename of the image.
317
+	 *                           Only used if $file is the image data.
318
+	 * @param bool   $isfile     Whether $file is a filename or not.
319
+	 *                           Defaults to true
320
+	 * @param string $content_id Desired Content-ID of MIME part
321
+	 *                           Defaults to generated unique ID
322
+	 *
323
+	 * @return bool          True on success
324
+	 * @access public
325
+	 */
326
+	function addHTMLImage($file,
327
+		$c_type='application/octet-stream',
328
+		$name = '',
329
+		$isfile = true,
330
+		$content_id = null
331
+	) {
332
+		$bodyfile = null;
333
+
334
+		if ($isfile) {
335
+			// Don't load file into memory
336
+			if ($this->_build_params['delay_file_io']) {
337
+				$filedata = null;
338
+				$bodyfile = $file;
339
+			} else {
340
+				if ($this->_isError($filedata = $this->_file2str($file))) {
341
+					return $filedata;
342
+				}
343
+			}
344
+			$filename = ($name ? $name : $file);
345
+		} else {
346
+			$filedata = $file;
347
+			$filename = $name;
348
+		}
349
+
350
+		if (!$content_id) {
351
+			$content_id = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true));
352
+		}
353
+
354
+		$this->_html_images[] = array(
355
+			'body'      => $filedata,
356
+			'body_file' => $bodyfile,
357
+			'name'      => $filename,
358
+			'c_type'    => $c_type,
359
+			'cid'       => $content_id
360
+		);
361
+
362
+		return true;
363
+	}
364
+
365
+	/**
366
+	 * Adds a file to the list of attachments.
367
+	 *
368
+	 * @param string $file        The file name of the file to attach
369
+	 *                            or the file contents itself
370
+	 * @param string $c_type      The content type
371
+	 * @param string $name        The filename of the attachment
372
+	 *                            Only use if $file is the contents
373
+	 * @param bool   $isfile      Whether $file is a filename or not. Defaults to true
374
+	 * @param string $encoding    The type of encoding to use. Defaults to base64.
375
+	 *                            Possible values: 7bit, 8bit, base64 or quoted-printable.
376
+	 * @param string $disposition The content-disposition of this file
377
+	 *                            Defaults to attachment.
378
+	 *                            Possible values: attachment, inline.
379
+	 * @param string $charset     The character set of attachment's content.
380
+	 * @param string $language    The language of the attachment
381
+	 * @param string $location    The RFC 2557.4 location of the attachment
382
+	 * @param string $n_encoding  Encoding of the attachment's name in Content-Type
383
+	 *                            By default filenames are encoded using RFC2231 method
384
+	 *                            Here you can set RFC2047 encoding (quoted-printable
385
+	 *                            or base64) instead
386
+	 * @param string $f_encoding  Encoding of the attachment's filename
387
+	 *                            in Content-Disposition header.
388
+	 * @param string $description Content-Description header
389
+	 * @param string $h_charset   The character set of the headers e.g. filename
390
+	 *                            If not specified, $charset will be used
391
+	 * @param array  $add_headers Additional part headers. Array keys can be in form
392
+	 *                            of <header_name>:<parameter_name>
393
+	 *
394
+	 * @return mixed              True on success or PEAR_Error object
395
+	 * @access public
396
+	 */
397
+	function addAttachment($file,
398
+		$c_type      = 'application/octet-stream',
399
+		$name        = '',
400
+		$isfile      = true,
401
+		$encoding    = 'base64',
402
+		$disposition = 'attachment',
403
+		$charset     = '',
404
+		$language    = '',
405
+		$location    = '',
406
+		$n_encoding  = null,
407
+		$f_encoding  = null,
408
+		$description = '',
409
+		$h_charset   = null,
410
+		$add_headers = array()
411
+	) {
412
+		$bodyfile = null;
413
+
414
+		if ($isfile) {
415
+			// Don't load file into memory
416
+			if ($this->_build_params['delay_file_io']) {
417
+				$filedata = null;
418
+				$bodyfile = $file;
419
+			} else {
420
+				if ($this->_isError($filedata = $this->_file2str($file))) {
421
+					return $filedata;
422
+				}
423
+			}
424
+			// Force the name the user supplied, otherwise use $file
425
+			$filename = ($name ? $name : $this->_basename($file));
426
+		} else {
427
+			$filedata = $file;
428
+			$filename = $name;
429
+		}
430
+
431
+		if (!strlen($filename)) {
432
+			$msg = "The supplied filename for the attachment can't be empty";
433
+			return $this->_raiseError($msg);
434
+		}
435
+
436
+		$this->_parts[] = array(
437
+			'body'        => $filedata,
438
+			'body_file'   => $bodyfile,
439
+			'name'        => $filename,
440
+			'c_type'      => $c_type,
441
+			'charset'     => $charset,
442
+			'encoding'    => $encoding,
443
+			'language'    => $language,
444
+			'location'    => $location,
445
+			'disposition' => $disposition,
446
+			'description' => $description,
447
+			'add_headers' => $add_headers,
448
+			'name_encoding'     => $n_encoding,
449
+			'filename_encoding' => $f_encoding,
450
+			'headers_charset'   => $h_charset,
451
+		);
452
+
453
+		return true;
454
+	}
455
+
456
+	/**
457
+	 * Get the contents of the given file name as string
458
+	 *
459
+	 * @param string $file_name Path of file to process
460
+	 *
461
+	 * @return string           Contents of $file_name
462
+	 * @access private
463
+	 */
464
+	function _file2str($file_name)
465
+	{
466
+		// Check state of file and raise an error properly
467
+		if (!file_exists($file_name)) {
468
+			return $this->_raiseError('File not found: ' . $file_name);
469
+		}
470
+		if (!is_file($file_name)) {
471
+			return $this->_raiseError('Not a regular file: ' . $file_name);
472
+		}
473
+		if (!is_readable($file_name)) {
474
+			return $this->_raiseError('File is not readable: ' . $file_name);
475
+		}
476
+
477
+		// Temporarily reset magic_quotes_runtime and read file contents
478
+		if ($magic_quote_setting = get_magic_quotes_runtime()) {
479
+			@ini_set('magic_quotes_runtime', 0);
480
+		}
481
+		$cont = file_get_contents($file_name);
482
+		if ($magic_quote_setting) {
483
+			@ini_set('magic_quotes_runtime', $magic_quote_setting);
484
+		}
485
+
486
+		return $cont;
487
+	}
488
+
489
+	/**
490
+	 * Adds a text subpart to the mimePart object and
491
+	 * returns it during the build process.
492
+	 *
493
+	 * @param mixed  &$obj The object to add the part to, or
494
+	 *                     anything else if a new object is to be created.
495
+	 * @param string $text The text to add.
496
+	 *
497
+	 * @return object      The text mimePart object
498
+	 * @access private
499
+	 */
500
+	function &_addTextPart(&$obj, $text = '')
501
+	{
502
+		$params['content_type'] = 'text/plain';
503
+		$params['encoding']     = $this->_build_params['text_encoding'];
504
+		$params['charset']      = $this->_build_params['text_charset'];
505
+		$params['eol']          = $this->_build_params['eol'];
506
+
507
+		if (is_object($obj)) {
508
+			$ret = $obj->addSubpart($text, $params);
509
+		} else {
510
+			$ret = new Mail_mimePart($text, $params);
511
+		}
512
+
513
+		return $ret;
514
+	}
515
+
516
+	/**
517
+	 * Adds a html subpart to the mimePart object and
518
+	 * returns it during the build process.
519
+	 *
520
+	 * @param mixed &$obj The object to add the part to, or
521
+	 *                    anything else if a new object is to be created.
522
+	 *
523
+	 * @return object     The html mimePart object
524
+	 * @access private
525
+	 */
526
+	function &_addHtmlPart(&$obj)
527
+	{
528
+		$params['content_type'] = 'text/html';
529
+		$params['encoding']     = $this->_build_params['html_encoding'];
530
+		$params['charset']      = $this->_build_params['html_charset'];
531
+		$params['eol']          = $this->_build_params['eol'];
532
+
533
+		if (is_object($obj)) {
534
+			$ret = $obj->addSubpart($this->_htmlbody, $params);
535
+		} else {
536
+			$ret = new Mail_mimePart($this->_htmlbody, $params);
537
+		}
538
+
539
+		return $ret;
540
+	}
541
+
542
+	/**
543
+	 * Creates a new mimePart object, using multipart/mixed as
544
+	 * the initial content-type and returns it during the
545
+	 * build process.
546
+	 *
547
+	 * @return object The multipart/mixed mimePart object
548
+	 * @access private
549
+	 */
550
+	function &_addMixedPart()
551
+	{
552
+		$params['content_type'] = 'multipart/mixed';
553
+		$params['eol']          = $this->_build_params['eol'];
554
+
555
+		// Create empty multipart/mixed Mail_mimePart object to return
556
+		$ret = new Mail_mimePart('', $params);
557
+		return $ret;
558
+	}
559
+
560
+	/**
561
+	 * Adds a multipart/alternative part to a mimePart
562
+	 * object (or creates one), and returns it during
563
+	 * the build process.
564
+	 *
565
+	 * @param mixed &$obj The object to add the part to, or
566
+	 *                    anything else if a new object is to be created.
567
+	 *
568
+	 * @return object     The multipart/mixed mimePart object
569
+	 * @access private
570
+	 */
571
+	function &_addAlternativePart(&$obj)
572
+	{
573
+		$params['content_type'] = 'multipart/alternative';
574
+		$params['eol']          = $this->_build_params['eol'];
575
+
576
+		if (is_object($obj)) {
577
+			$ret = $obj->addSubpart('', $params);
578
+		} else {
579
+			$ret = new Mail_mimePart('', $params);
580
+		}
581
+
582
+		return $ret;
583
+	}
584
+
585
+	/**
586
+	 * Adds a multipart/related part to a mimePart
587
+	 * object (or creates one), and returns it during
588
+	 * the build process.
589
+	 *
590
+	 * @param mixed &$obj The object to add the part to, or
591
+	 *                    anything else if a new object is to be created
592
+	 *
593
+	 * @return object     The multipart/mixed mimePart object
594
+	 * @access private
595
+	 */
596
+	function &_addRelatedPart(&$obj)
597
+	{
598
+		$params['content_type'] = 'multipart/related';
599
+		$params['eol']          = $this->_build_params['eol'];
600
+
601
+		if (is_object($obj)) {
602
+			$ret = $obj->addSubpart('', $params);
603
+		} else {
604
+			$ret = new Mail_mimePart('', $params);
605
+		}
606
+
607
+		return $ret;
608
+	}
609
+
610
+	/**
611
+	 * Adds an html image subpart to a mimePart object
612
+	 * and returns it during the build process.
613
+	 *
614
+	 * @param object &$obj  The mimePart to add the image to
615
+	 * @param array  $value The image information
616
+	 *
617
+	 * @return object       The image mimePart object
618
+	 * @access private
619
+	 */
620
+	function &_addHtmlImagePart(&$obj, $value)
621
+	{
622
+		$params['content_type'] = $value['c_type'];
623
+		$params['encoding']     = 'base64';
624
+		$params['disposition']  = 'inline';
625
+		$params['filename']     = $value['name'];
626
+		$params['cid']          = $value['cid'];
627
+		$params['body_file']    = $value['body_file'];
628
+		$params['eol']          = $this->_build_params['eol'];
629
+
630
+		if (!empty($value['name_encoding'])) {
631
+			$params['name_encoding'] = $value['name_encoding'];
632
+		}
633
+		if (!empty($value['filename_encoding'])) {
634
+			$params['filename_encoding'] = $value['filename_encoding'];
635
+		}
636
+
637
+		$ret = $obj->addSubpart($value['body'], $params);
638
+		return $ret;
639
+	}
640
+
641
+	/**
642
+	 * Adds an attachment subpart to a mimePart object
643
+	 * and returns it during the build process.
644
+	 *
645
+	 * @param object &$obj  The mimePart to add the image to
646
+	 * @param array  $value The attachment information
647
+	 *
648
+	 * @return object       The image mimePart object
649
+	 * @access private
650
+	 */
651
+	function &_addAttachmentPart(&$obj, $value)
652
+	{
653
+		$params['eol']          = $this->_build_params['eol'];
654
+		$params['filename']     = $value['name'];
655
+		$params['encoding']     = $value['encoding'];
656
+		$params['content_type'] = $value['c_type'];
657
+		$params['body_file']    = $value['body_file'];
658
+		$params['disposition']  = isset($value['disposition']) ? 
659
+								  $value['disposition'] : 'attachment';
660
+
661
+		// content charset
662
+		if (!empty($value['charset'])) {
663
+			$params['charset'] = $value['charset'];
664
+		}
665
+		// headers charset (filename, description)
666
+		if (!empty($value['headers_charset'])) {
667
+			$params['headers_charset'] = $value['headers_charset'];
668
+		}
669
+		if (!empty($value['language'])) {
670
+			$params['language'] = $value['language'];
671
+		}
672
+		if (!empty($value['location'])) {
673
+			$params['location'] = $value['location'];
674
+		}
675
+		if (!empty($value['name_encoding'])) {
676
+			$params['name_encoding'] = $value['name_encoding'];
677
+		}
678
+		if (!empty($value['filename_encoding'])) {
679
+			$params['filename_encoding'] = $value['filename_encoding'];
680
+		}
681
+		if (!empty($value['description'])) {
682
+			$params['description'] = $value['description'];
683
+		}
684
+		if (is_array($value['add_headers'])) {
685
+			$params['headers'] = $value['add_headers'];
686
+		}
687
+
688
+		$ret = $obj->addSubpart($value['body'], $params);
689
+		return $ret;
690
+	}
691
+
692
+	/**
693
+	 * Returns the complete e-mail, ready to send using an alternative
694
+	 * mail delivery method. Note that only the mailpart that is made
695
+	 * with Mail_Mime is created. This means that,
696
+	 * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF 
697
+	 * using the $headers parameter!
698
+	 * 
699
+	 * @param string $separation The separation between these two parts.
700
+	 * @param array  $params     The Build parameters passed to the
701
+	 *                           get() function. See get() for more info.
702
+	 * @param array  $headers    The extra headers that should be passed
703
+	 *                           to the headers() method.
704
+	 *                           See that function for more info.
705
+	 * @param bool   $overwrite  Overwrite the existing headers with new.
706
+	 *
707
+	 * @return mixed The complete e-mail or PEAR error object
708
+	 * @access public
709
+	 */
710
+	function getMessage($separation = null, $params = null, $headers = null,
711
+		$overwrite = false
712
+	) {
713
+		if ($separation === null) {
714
+			$separation = $this->_build_params['eol'];
715
+		}
716
+
717
+		$body = $this->get($params);
718
+
719
+		if ($this->_isError($body)) {
720
+			return $body;
721
+		}
722
+
723
+		return $this->txtHeaders($headers, $overwrite) . $separation . $body;
724
+	}
725
+
726
+	/**
727
+	 * Returns the complete e-mail body, ready to send using an alternative
728
+	 * mail delivery method.
729
+	 * 
730
+	 * @param array $params The Build parameters passed to the
731
+	 *                      get() method. See get() for more info.
732
+	 *
733
+	 * @return mixed The e-mail body or PEAR error object
734
+	 * @access public
735
+	 * @since 1.6.0
736
+	 */
737
+	function getMessageBody($params = null)
738
+	{
739
+		return $this->get($params, null, true);
740
+	}
741
+
742
+	/**
743
+	 * Writes (appends) the complete e-mail into file.
744
+	 * 
745
+	 * @param string $filename  Output file location
746
+	 * @param array  $params    The Build parameters passed to the
747
+	 *                          get() method. See get() for more info.
748
+	 * @param array  $headers   The extra headers that should be passed
749
+	 *                          to the headers() function.
750
+	 *                          See that function for more info.
751
+	 * @param bool   $overwrite Overwrite the existing headers with new.
752
+	 *
753
+	 * @return mixed True or PEAR error object
754
+	 * @access public
755
+	 * @since 1.6.0
756
+	 */
757
+	function saveMessage($filename, $params = null, $headers = null, $overwrite = false)
758
+	{
759
+		// Check state of file and raise an error properly
760
+		if (file_exists($filename) && !is_writable($filename)) {
761
+			return $this->_raiseError('File is not writable: ' . $filename);
762
+		}
763
+
764
+		// Temporarily reset magic_quotes_runtime and read file contents
765
+		if ($magic_quote_setting = get_magic_quotes_runtime()) {
766
+			@ini_set('magic_quotes_runtime', 0);
767
+		}
768
+
769
+		if (!($fh = fopen($filename, 'ab'))) {
770
+			return $this->_raiseError('Unable to open file: ' . $filename);
771
+		}
772
+
773
+		// Write message headers into file (skipping Content-* headers)
774
+		$head = $this->txtHeaders($headers, $overwrite, true);
775
+		if (fwrite($fh, $head) === false) {
776
+			return $this->_raiseError('Error writing to file: ' . $filename);
777
+		}
778
+
779
+		fclose($fh);
780
+
781
+		if ($magic_quote_setting) {
782
+			@ini_set('magic_quotes_runtime', $magic_quote_setting);
783
+		}
784
+
785
+		// Write the rest of the message into file
786
+		$res = $this->get($params, $filename);
787
+
788
+		return $res ? $res : true;
789
+	}
790
+
791
+	/**
792
+	 * Writes (appends) the complete e-mail body into file.
793
+	 *
794
+	 * @param string $filename Output file location
795
+	 * @param array  $params   The Build parameters passed to the
796
+	 *                         get() method. See get() for more info.
797
+	 *
798
+	 * @return mixed True or PEAR error object
799
+	 * @access public
800
+	 * @since 1.6.0
801
+	 */
802
+	function saveMessageBody($filename, $params = null)
803
+	{
804
+		// Check state of file and raise an error properly
805
+		if (file_exists($filename) && !is_writable($filename)) {
806
+			return $this->_raiseError('File is not writable: ' . $filename);
807
+		}
808
+
809
+		// Temporarily reset magic_quotes_runtime and read file contents
810
+		if ($magic_quote_setting = get_magic_quotes_runtime()) {
811
+			@ini_set('magic_quotes_runtime', 0);
812
+		}
813
+
814
+		if (!($fh = fopen($filename, 'ab'))) {
815
+			return $this->_raiseError('Unable to open file: ' . $filename);
816
+		}
817
+
818
+		// Write the rest of the message into file
819
+		$res = $this->get($params, $filename, true);
820
+
821
+		return $res ? $res : true;
822
+	}
823
+
824
+	/**
825
+	 * Builds the multipart message from the list ($this->_parts) and
826
+	 * returns the mime content.
827
+	 *
828
+	 * @param array    $params    Build parameters that change the way the email
829
+	 *                            is built. Should be associative. See $_build_params.
830
+	 * @param resource $filename  Output file where to save the message instead of
831
+	 *                            returning it
832
+	 * @param boolean  $skip_head True if you want to return/save only the message
833
+	 *                            without headers
834
+	 *
835
+	 * @return mixed The MIME message content string, null or PEAR error object
836
+	 * @access public
837
+	 */
838
+	function get($params = null, $filename = null, $skip_head = false)
839
+	{
840
+		if (isset($params)) {
841
+			while (list($key, $value) = each($params)) {
842
+				$this->_build_params[$key] = $value;
843
+			}
844
+		}
845
+
846
+		if (isset($this->_headers['From'])) {
847
+			// Bug #11381: Illegal characters in domain ID
848
+			if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->_headers['From'], $matches)) {
849
+				$domainID = $matches[1];
850
+			} else {
851
+				$domainID = '@localhost';
852
+			}
853
+			foreach ($this->_html_images as $i => $img) {
854
+				$cid = $this->_html_images[$i]['cid']; 
855
+				if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) {
856
+					$this->_html_images[$i]['cid'] = $cid . $domainID;
857
+				}
858
+			}
859
+		}
860
+
861
+		if (count($this->_html_images) && isset($this->_htmlbody)) {
862
+			foreach ($this->_html_images as $key => $value) {
863
+				$regex   = array();
864
+				$regex[] = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' .
865
+							preg_quote($value['name'], '#') . '\3#';
866
+				$regex[] = '#(?i)url(?-i)\(\s*(["\']?)' .
867
+							preg_quote($value['name'], '#') . '\1\s*\)#';
868
+
869
+				$rep   = array();
870
+				$rep[] = '\1\2=\3cid:' . $value['cid'] .'\3';
871
+				$rep[] = 'url(\1cid:' . $value['cid'] . '\1)';
872
+
873
+				$this->_htmlbody = preg_replace($regex, $rep, $this->_htmlbody);
874
+				$this->_html_images[$key]['name']
875
+					= $this->_basename($this->_html_images[$key]['name']);
876
+			}
877
+		}
878
+
879
+		$this->_checkParams();
880
+
881
+		$null        = -1;
882
+		$attachments = count($this->_parts) > 0;
883
+		$html_images = count($this->_html_images) > 0;
884
+		$html        = strlen($this->_htmlbody) > 0;
885
+		$text        = !$html && strlen($this->_txtbody);
886
+
887
+		switch (true) {
888
+		case $text && !$attachments:
889
+			$message =& $this->_addTextPart($null, $this->_txtbody);
890
+			break;
891
+
892
+		case !$text && !$html && $attachments:
893
+			$message =& $this->_addMixedPart();
894
+			for ($i = 0; $i < count($this->_parts); $i++) {
895
+				$this->_addAttachmentPart($message, $this->_parts[$i]);
896
+			}
897
+			break;
898
+
899
+		case $text && $attachments:
900
+			$message =& $this->_addMixedPart();
901
+			$this->_addTextPart($message, $this->_txtbody);
902
+			for ($i = 0; $i < count($this->_parts); $i++) {
903
+				$this->_addAttachmentPart($message, $this->_parts[$i]);
904
+			}
905
+			break;
906
+
907
+		case $html && !$attachments && !$html_images:
908
+			if (isset($this->_txtbody)) {
909
+				$message =& $this->_addAlternativePart($null);
910
+				$this->_addTextPart($message, $this->_txtbody);
911
+				$this->_addHtmlPart($message);
912
+			} else {
913
+				$message =& $this->_addHtmlPart($null);
914
+			}
915
+			break;
916
+
917
+		case $html && !$attachments && $html_images:
918
+			// * Content-Type: multipart/alternative;
919
+			//    * text
920
+			//    * Content-Type: multipart/related;
921
+			//       * html
922
+			//       * image...
923
+			if (isset($this->_txtbody)) {
924
+				$message =& $this->_addAlternativePart($null);
925
+				$this->_addTextPart($message, $this->_txtbody);
926
+
927
+				$ht =& $this->_addRelatedPart($message);
928
+				$this->_addHtmlPart($ht);
929
+				for ($i = 0; $i < count($this->_html_images); $i++) {
930
+					$this->_addHtmlImagePart($ht, $this->_html_images[$i]);
931
+				}
932
+			} else {
933
+				// * Content-Type: multipart/related;
934
+				//    * html
935
+				//    * image...
936
+				$message =& $this->_addRelatedPart($null);
937
+				$this->_addHtmlPart($message);
938
+				for ($i = 0; $i < count($this->_html_images); $i++) {
939
+					$this->_addHtmlImagePart($message, $this->_html_images[$i]);
940
+				}
941
+			}
942
+			/*
943 943
             // #13444, #9725: the code below was a non-RFC compliant hack
944 944
             // * Content-Type: multipart/related;
945 945
             //    * Content-Type: multipart/alternative;
@@ -958,537 +958,537 @@  discard block
 block discarded – undo
958 958
                 $this->_addHtmlImagePart($message, $this->_html_images[$i]);
959 959
             }
960 960
             */
961
-            break;
962
-
963
-        case $html && $attachments && !$html_images:
964
-            $message =& $this->_addMixedPart();
965
-            if (isset($this->_txtbody)) {
966
-                $alt =& $this->_addAlternativePart($message);
967
-                $this->_addTextPart($alt, $this->_txtbody);
968
-                $this->_addHtmlPart($alt);
969
-            } else {
970
-                $this->_addHtmlPart($message);
971
-            }
972
-            for ($i = 0; $i < count($this->_parts); $i++) {
973
-                $this->_addAttachmentPart($message, $this->_parts[$i]);
974
-            }
975
-            break;
976
-
977
-        case $html && $attachments && $html_images:
978
-            $message =& $this->_addMixedPart();
979
-            if (isset($this->_txtbody)) {
980
-                $alt =& $this->_addAlternativePart($message);
981
-                $this->_addTextPart($alt, $this->_txtbody);
982
-                $rel =& $this->_addRelatedPart($alt);
983
-            } else {
984
-                $rel =& $this->_addRelatedPart($message);
985
-            }
986
-            $this->_addHtmlPart($rel);
987
-            for ($i = 0; $i < count($this->_html_images); $i++) {
988
-                $this->_addHtmlImagePart($rel, $this->_html_images[$i]);
989
-            }
990
-            for ($i = 0; $i < count($this->_parts); $i++) {
991
-                $this->_addAttachmentPart($message, $this->_parts[$i]);
992
-            }
993
-            break;
994
-        }
995
-
996
-        if (!isset($message)) {
997
-            return null;
998
-        }
999
-
1000
-        // Use saved boundary
1001
-        if (!empty($this->_build_params['boundary'])) {
1002
-            $boundary = $this->_build_params['boundary'];
1003
-        } else {
1004
-            $boundary = null;
1005
-        }
1006
-
1007
-        // Write output to file
1008
-        if ($filename) {
1009
-            // Append mimePart message headers and body into file
1010
-            $headers = $message->encodeToFile($filename, $boundary, $skip_head);
1011
-            if ($this->_isError($headers)) {
1012
-                return $headers;
1013
-            }
1014
-            $this->_headers = array_merge($this->_headers, $headers);
1015
-            return null;
1016
-        } else {
1017
-            $output = $message->encode($boundary, $skip_head);
1018
-            if ($this->_isError($output)) {
1019
-                return $output;
1020
-            }
1021
-            $this->_headers = array_merge($this->_headers, $output['headers']);
1022
-            return $output['body'];
1023
-        }
1024
-    }
1025
-
1026
-    /**
1027
-     * Returns an array with the headers needed to prepend to the email
1028
-     * (MIME-Version and Content-Type). Format of argument is:
1029
-     * $array['header-name'] = 'header-value';
1030
-     *
1031
-     * @param array $xtra_headers Assoc array with any extra headers (optional)
1032
-     *                            (Don't set Content-Type for multipart messages here!)
1033
-     * @param bool  $overwrite    Overwrite already existing headers.
1034
-     * @param bool  $skip_content Don't return content headers: Content-Type,
1035
-     *                            Content-Disposition and Content-Transfer-Encoding
1036
-     * 
1037
-     * @return array              Assoc array with the mime headers
1038
-     * @access public
1039
-     */
1040
-    function headers($xtra_headers = null, $overwrite = false, $skip_content = false)
1041
-    {
1042
-        // Add mime version header
1043
-        $headers['MIME-Version'] = '1.0';
1044
-
1045
-        // Content-Type and Content-Transfer-Encoding headers should already
1046
-        // be present if get() was called, but we'll re-set them to make sure
1047
-        // we got them when called before get() or something in the message
1048
-        // has been changed after get() [#14780]
1049
-        if (!$skip_content) {
1050
-            $headers += $this->_contentHeaders();
1051
-        }
1052
-
1053
-        if (!empty($xtra_headers)) {
1054
-            $headers = array_merge($headers, $xtra_headers);
1055
-        }
1056
-
1057
-        if ($overwrite) {
1058
-            $this->_headers = array_merge($this->_headers, $headers);
1059
-        } else {
1060
-            $this->_headers = array_merge($headers, $this->_headers);
1061
-        }
1062
-
1063
-        $headers = $this->_headers;
1064
-
1065
-        if ($skip_content) {
1066
-            unset($headers['Content-Type']);
1067
-            unset($headers['Content-Transfer-Encoding']);
1068
-            unset($headers['Content-Disposition']);
1069
-        } else if (!empty($this->_build_params['ctype'])) {
1070
-            $headers['Content-Type'] = $this->_build_params['ctype'];
1071
-        }
1072
-
1073
-        $encodedHeaders = $this->_encodeHeaders($headers);
1074
-        return $encodedHeaders;
1075
-    }
1076
-
1077
-    /**
1078
-     * Get the text version of the headers
1079
-     * (usefull if you want to use the PHP mail() function)
1080
-     *
1081
-     * @param array $xtra_headers Assoc array with any extra headers (optional)
1082
-     *                            (Don't set Content-Type for multipart messages here!)
1083
-     * @param bool  $overwrite    Overwrite the existing headers with new.
1084
-     * @param bool  $skip_content Don't return content headers: Content-Type,
1085
-     *                            Content-Disposition and Content-Transfer-Encoding
1086
-     *
1087
-     * @return string             Plain text headers
1088
-     * @access public
1089
-     */
1090
-    function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false)
1091
-    {
1092
-        $headers = $this->headers($xtra_headers, $overwrite, $skip_content);
1093
-
1094
-        // Place Received: headers at the beginning of the message
1095
-        // Spam detectors often flag messages with it after the Subject: as spam
1096
-        if (isset($headers['Received'])) {
1097
-            $received = $headers['Received'];
1098
-            unset($headers['Received']);
1099
-            $headers = array('Received' => $received) + $headers;
1100
-        }
1101
-
1102
-        $ret = '';
1103
-        $eol = $this->_build_params['eol'];
1104
-
1105
-        foreach ($headers as $key => $val) {
1106
-            if (is_array($val)) {
1107
-                foreach ($val as $value) {
1108
-                    $ret .= "$key: $value" . $eol;
1109
-                }
1110
-            } else {
1111
-                $ret .= "$key: $val" . $eol;
1112
-            }
1113
-        }
1114
-
1115
-        return $ret;
1116
-    }
1117
-
1118
-    /**
1119
-     * Sets message Content-Type header.
1120
-     * Use it to build messages with various content-types e.g. miltipart/raport
1121
-     * not supported by _contentHeaders() function.
1122
-     *
1123
-     * @param string $type   Type name
1124
-     * @param array  $params Hash array of header parameters
1125
-     *
1126
-     * @return void
1127
-     * @access public
1128
-     * @since 1.7.0
1129
-     */
1130
-    function setContentType($type, $params = array())
1131
-    {
1132
-        $header = $type;
1133
-
1134
-        $eol = !empty($this->_build_params['eol'])
1135
-            ? $this->_build_params['eol'] : "\r\n";
1136
-
1137
-        // add parameters
1138
-        $token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
1139
-            . '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
1140
-        if (is_array($params)) {
1141
-            foreach ($params as $name => $value) {
1142
-                if ($name == 'boundary') {
1143
-                    $this->_build_params['boundary'] = $value;
1144
-                }
1145
-                if (!preg_match($token_regexp, $value)) {
1146
-                    $header .= ";$eol $name=$value";
1147
-                } else {
1148
-                    $value = addcslashes($value, '\\"');
1149
-                    $header .= ";$eol $name=\"$value\"";
1150
-                }
1151
-            }
1152
-        }
1153
-
1154
-        // add required boundary parameter if not defined
1155
-        if (preg_match('/^multipart\//i', $type)) {
1156
-            if (empty($this->_build_params['boundary'])) {
1157
-                $this->_build_params['boundary'] = '=_' . md5(rand() . microtime());
1158
-            }
1159
-
1160
-            $header .= ";$eol boundary=\"".$this->_build_params['boundary']."\"";
1161
-        }
1162
-
1163
-        $this->_build_params['ctype'] = $header;
1164
-    }
1165
-
1166
-    /**
1167
-     * Sets the Subject header
1168
-     *
1169
-     * @param string $subject String to set the subject to.
1170
-     *
1171
-     * @return void
1172
-     * @access public
1173
-     */
1174
-    function setSubject($subject)
1175
-    {
1176
-        $this->_headers['Subject'] = $subject;
1177
-    }
1178
-
1179
-    /**
1180
-     * Set an email to the From (the sender) header
1181
-     *
1182
-     * @param string $email The email address to use
1183
-     *
1184
-     * @return void
1185
-     * @access public
1186
-     */
1187
-    function setFrom($email)
1188
-    {
1189
-        $this->_headers['From'] = $email;
1190
-    }
1191
-
1192
-    /**
1193
-     * Add an email to the To header
1194
-     * (multiple calls to this method are allowed)
1195
-     *
1196
-     * @param string $email The email direction to add
1197
-     *
1198
-     * @return void
1199
-     * @access public
1200
-     */
1201
-    function addTo($email)
1202
-    {
1203
-        if (isset($this->_headers['To'])) {
1204
-            $this->_headers['To'] .= ", $email";
1205
-        } else {
1206
-            $this->_headers['To'] = $email;
1207
-        }
1208
-    }
1209
-
1210
-    /**
1211
-     * Add an email to the Cc (carbon copy) header
1212
-     * (multiple calls to this method are allowed)
1213
-     *
1214
-     * @param string $email The email direction to add
1215
-     *
1216
-     * @return void
1217
-     * @access public
1218
-     */
1219
-    function addCc($email)
1220
-    {
1221
-        if (isset($this->_headers['Cc'])) {
1222
-            $this->_headers['Cc'] .= ", $email";
1223
-        } else {
1224
-            $this->_headers['Cc'] = $email;
1225
-        }
1226
-    }
1227
-
1228
-    /**
1229
-     * Add an email to the Bcc (blank carbon copy) header
1230
-     * (multiple calls to this method are allowed)
1231
-     *
1232
-     * @param string $email The email direction to add
1233
-     *
1234
-     * @return void
1235
-     * @access public
1236
-     */
1237
-    function addBcc($email)
1238
-    {
1239
-        if (isset($this->_headers['Bcc'])) {
1240
-            $this->_headers['Bcc'] .= ", $email";
1241
-        } else {
1242
-            $this->_headers['Bcc'] = $email;
1243
-        }
1244
-    }
1245
-
1246
-    /**
1247
-     * Since the PHP send function requires you to specify
1248
-     * recipients (To: header) separately from the other
1249
-     * headers, the To: header is not properly encoded.
1250
-     * To fix this, you can use this public method to 
1251
-     * encode your recipients before sending to the send
1252
-     * function
1253
-     *
1254
-     * @param string $recipients A comma-delimited list of recipients
1255
-     *
1256
-     * @return string            Encoded data
1257
-     * @access public
1258
-     */
1259
-    function encodeRecipients($recipients)
1260
-    {
1261
-        $input = array("To" => $recipients);
1262
-        $retval = $this->_encodeHeaders($input);
1263
-        return $retval["To"] ;
1264
-    }
1265
-
1266
-    /**
1267
-     * Encodes headers as per RFC2047
1268
-     *
1269
-     * @param array $input  The header data to encode
1270
-     * @param array $params Extra build parameters
1271
-     *
1272
-     * @return array        Encoded data
1273
-     * @access private
1274
-     */
1275
-    function _encodeHeaders($input, $params = array())
1276
-    {
1277
-        $build_params = $this->_build_params;
1278
-        while (list($key, $value) = each($params)) {
1279
-            $build_params[$key] = $value;
1280
-        }
1281
-
1282
-        foreach ($input as $hdr_name => $hdr_value) {
1283
-            if (is_array($hdr_value)) {
1284
-                foreach ($hdr_value as $idx => $value) {
1285
-                    $input[$hdr_name][$idx] = $this->encodeHeader(
1286
-                        $hdr_name, $value,
1287
-                        $build_params['head_charset'], $build_params['head_encoding']
1288
-                    );
1289
-                }
1290
-            } else {
1291
-                $input[$hdr_name] = $this->encodeHeader(
1292
-                    $hdr_name, $hdr_value,
1293
-                    $build_params['head_charset'], $build_params['head_encoding']
1294
-                );
1295
-            }
1296
-        }
1297
-
1298
-        return $input;
1299
-    }
1300
-
1301
-    /**
1302
-     * Encodes a header as per RFC2047
1303
-     *
1304
-     * @param string $name     The header name
1305
-     * @param string $value    The header data to encode
1306
-     * @param string $charset  Character set name
1307
-     * @param string $encoding Encoding name (base64 or quoted-printable)
1308
-     *
1309
-     * @return string          Encoded header data (without a name)
1310
-     * @access public
1311
-     * @since 1.5.3
1312
-     */
1313
-    function encodeHeader($name, $value, $charset, $encoding)
1314
-    {
1315
-        $mime_part = new Mail_mimePart;
1316
-        return $mime_part->encodeHeader(
1317
-            $name, $value, $charset, $encoding, $this->_build_params['eol']
1318
-        );
1319
-    }
1320
-
1321
-    /**
1322
-     * Get file's basename (locale independent) 
1323
-     *
1324
-     * @param string $filename Filename
1325
-     *
1326
-     * @return string          Basename
1327
-     * @access private
1328
-     */
1329
-    function _basename($filename)
1330
-    {
1331
-        // basename() is not unicode safe and locale dependent
1332
-        if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
1333
-            return preg_replace('/^.*[\\\\\\/]/', '', $filename);
1334
-        } else {
1335
-            return preg_replace('/^.*[\/]/', '', $filename);
1336
-        }
1337
-    }
1338
-
1339
-    /**
1340
-     * Get Content-Type and Content-Transfer-Encoding headers of the message
1341
-     *
1342
-     * @return array Headers array
1343
-     * @access private
1344
-     */
1345
-    function _contentHeaders()
1346
-    {
1347
-        $attachments = count($this->_parts)                 ? true : false;
1348
-        $html_images = count($this->_html_images)           ? true : false;
1349
-        $html        = strlen($this->_htmlbody)             ? true : false;
1350
-        $text        = (!$html && strlen($this->_txtbody))  ? true : false;
1351
-        $headers     = array();
1352
-
1353
-        // See get()
1354
-        switch (true) {
1355
-        case $text && !$attachments:
1356
-            $headers['Content-Type'] = 'text/plain';
1357
-            break;
1358
-
1359
-        case !$text && !$html && $attachments:
1360
-        case $text && $attachments:
1361
-        case $html && $attachments && !$html_images:
1362
-        case $html && $attachments && $html_images:
1363
-            $headers['Content-Type'] = 'multipart/mixed';
1364
-            break;
1365
-
1366
-        case $html && !$attachments && !$html_images && isset($this->_txtbody):
1367
-        case $html && !$attachments && $html_images && isset($this->_txtbody):
1368
-            $headers['Content-Type'] = 'multipart/alternative';
1369
-            break;
1370
-
1371
-        case $html && !$attachments && !$html_images && !isset($this->_txtbody):
1372
-            $headers['Content-Type'] = 'text/html';
1373
-            break;
1374
-
1375
-        case $html && !$attachments && $html_images && !isset($this->_txtbody):
1376
-            $headers['Content-Type'] = 'multipart/related';
1377
-            break;
1378
-
1379
-        default:
1380
-            return $headers;
1381
-        }
1382
-
1383
-        $this->_checkParams();
1384
-
1385
-        $eol = !empty($this->_build_params['eol'])
1386
-            ? $this->_build_params['eol'] : "\r\n";
1387
-
1388
-        if ($headers['Content-Type'] == 'text/plain') {
1389
-            // single-part message: add charset and encoding
1390
-            $charset = 'charset=' . $this->_build_params['text_charset'];
1391
-            // place charset parameter in the same line, if possible
1392
-            // 26 = strlen("Content-Type: text/plain; ")
1393
-            $headers['Content-Type']
1394
-                .= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset";
1395
-            $headers['Content-Transfer-Encoding']
1396
-                = $this->_build_params['text_encoding'];
1397
-        } else if ($headers['Content-Type'] == 'text/html') {
1398
-            // single-part message: add charset and encoding
1399
-            $charset = 'charset=' . $this->_build_params['html_charset'];
1400
-            // place charset parameter in the same line, if possible
1401
-            $headers['Content-Type']
1402
-                .= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset";
1403
-            $headers['Content-Transfer-Encoding']
1404
-                = $this->_build_params['html_encoding'];
1405
-        } else {
1406
-            // multipart message: and boundary
1407
-            if (!empty($this->_build_params['boundary'])) {
1408
-                $boundary = $this->_build_params['boundary'];
1409
-            } else if (!empty($this->_headers['Content-Type'])
1410
-                && preg_match('/boundary="([^"]+)"/', $this->_headers['Content-Type'], $m)
1411
-            ) {
1412
-                $boundary = $m[1];
1413
-            } else {
1414
-                $boundary = '=_' . md5(rand() . microtime());
1415
-            }
1416
-
1417
-            $this->_build_params['boundary'] = $boundary;
1418
-            $headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
1419
-        }
1420
-
1421
-        return $headers;
1422
-    }
1423
-
1424
-    /**
1425
-     * Validate and set build parameters
1426
-     *
1427
-     * @return void
1428
-     * @access private
1429
-     */
1430
-    function _checkParams()
1431
-    {
1432
-        $encodings = array('7bit', '8bit', 'base64', 'quoted-printable');
1433
-
1434
-        $this->_build_params['text_encoding']
1435
-            = strtolower($this->_build_params['text_encoding']);
1436
-        $this->_build_params['html_encoding']
1437
-            = strtolower($this->_build_params['html_encoding']);
1438
-
1439
-        if (!in_array($this->_build_params['text_encoding'], $encodings)) {
1440
-            $this->_build_params['text_encoding'] = '7bit';
1441
-        }
1442
-        if (!in_array($this->_build_params['html_encoding'], $encodings)) {
1443
-            $this->_build_params['html_encoding'] = '7bit';
1444
-        }
1445
-
1446
-        // text body
1447
-        if ($this->_build_params['text_encoding'] == '7bit'
1448
-            && !preg_match('/ascii/i', $this->_build_params['text_charset'])
1449
-            && preg_match('/[^\x00-\x7F]/', $this->_txtbody)
1450
-        ) {
1451
-            $this->_build_params['text_encoding'] = 'quoted-printable';
1452
-        }
1453
-        // html body
1454
-        if ($this->_build_params['html_encoding'] == '7bit'
1455
-            && !preg_match('/ascii/i', $this->_build_params['html_charset'])
1456
-            && preg_match('/[^\x00-\x7F]/', $this->_htmlbody)
1457
-        ) {
1458
-            $this->_build_params['html_encoding'] = 'quoted-printable';
1459
-        }
1460
-    }
1461
-
1462
-    /**
1463
-     * PEAR::isError implementation
1464
-     *
1465
-     * @param mixed $data Object
1466
-     *
1467
-     * @return bool True if object is an instance of PEAR_Error
1468
-     * @access private
1469
-     */
1470
-    function _isError($data)
1471
-    {
1472
-        // PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
1473
-        if (is_object($data) && is_a($data, 'PEAR_Error')) {
1474
-            return true;
1475
-        }
1476
-
1477
-        return false;
1478
-    }
1479
-
1480
-    /**
1481
-     * PEAR::raiseError implementation
1482
-     *
1483
-     * @param $message A text error message
1484
-     *
1485
-     * @return PEAR_Error Instance of PEAR_Error
1486
-     * @access private
1487
-     */
1488
-    function _raiseError($message)
1489
-    {
1490
-        // PEAR::raiseError() is not PHP 5.4 compatible
1491
-        return new PEAR_Error($message);
1492
-    }
961
+			break;
962
+
963
+		case $html && $attachments && !$html_images:
964
+			$message =& $this->_addMixedPart();
965
+			if (isset($this->_txtbody)) {
966
+				$alt =& $this->_addAlternativePart($message);
967
+				$this->_addTextPart($alt, $this->_txtbody);
968
+				$this->_addHtmlPart($alt);
969
+			} else {
970
+				$this->_addHtmlPart($message);
971
+			}
972
+			for ($i = 0; $i < count($this->_parts); $i++) {
973
+				$this->_addAttachmentPart($message, $this->_parts[$i]);
974
+			}
975
+			break;
976
+
977
+		case $html && $attachments && $html_images:
978
+			$message =& $this->_addMixedPart();
979
+			if (isset($this->_txtbody)) {
980
+				$alt =& $this->_addAlternativePart($message);
981
+				$this->_addTextPart($alt, $this->_txtbody);
982
+				$rel =& $this->_addRelatedPart($alt);
983
+			} else {
984
+				$rel =& $this->_addRelatedPart($message);
985
+			}
986
+			$this->_addHtmlPart($rel);
987
+			for ($i = 0; $i < count($this->_html_images); $i++) {
988
+				$this->_addHtmlImagePart($rel, $this->_html_images[$i]);
989
+			}
990
+			for ($i = 0; $i < count($this->_parts); $i++) {
991
+				$this->_addAttachmentPart($message, $this->_parts[$i]);
992
+			}
993
+			break;
994
+		}
995
+
996
+		if (!isset($message)) {
997
+			return null;
998
+		}
999
+
1000
+		// Use saved boundary
1001
+		if (!empty($this->_build_params['boundary'])) {
1002
+			$boundary = $this->_build_params['boundary'];
1003
+		} else {
1004
+			$boundary = null;
1005
+		}
1006
+
1007
+		// Write output to file
1008
+		if ($filename) {
1009
+			// Append mimePart message headers and body into file
1010
+			$headers = $message->encodeToFile($filename, $boundary, $skip_head);
1011
+			if ($this->_isError($headers)) {
1012
+				return $headers;
1013
+			}
1014
+			$this->_headers = array_merge($this->_headers, $headers);
1015
+			return null;
1016
+		} else {
1017
+			$output = $message->encode($boundary, $skip_head);
1018
+			if ($this->_isError($output)) {
1019
+				return $output;
1020
+			}
1021
+			$this->_headers = array_merge($this->_headers, $output['headers']);
1022
+			return $output['body'];
1023
+		}
1024
+	}
1025
+
1026
+	/**
1027
+	 * Returns an array with the headers needed to prepend to the email
1028
+	 * (MIME-Version and Content-Type). Format of argument is:
1029
+	 * $array['header-name'] = 'header-value';
1030
+	 *
1031
+	 * @param array $xtra_headers Assoc array with any extra headers (optional)
1032
+	 *                            (Don't set Content-Type for multipart messages here!)
1033
+	 * @param bool  $overwrite    Overwrite already existing headers.
1034
+	 * @param bool  $skip_content Don't return content headers: Content-Type,
1035
+	 *                            Content-Disposition and Content-Transfer-Encoding
1036
+	 * 
1037
+	 * @return array              Assoc array with the mime headers
1038
+	 * @access public
1039
+	 */
1040
+	function headers($xtra_headers = null, $overwrite = false, $skip_content = false)
1041
+	{
1042
+		// Add mime version header
1043
+		$headers['MIME-Version'] = '1.0';
1044
+
1045
+		// Content-Type and Content-Transfer-Encoding headers should already
1046
+		// be present if get() was called, but we'll re-set them to make sure
1047
+		// we got them when called before get() or something in the message
1048
+		// has been changed after get() [#14780]
1049
+		if (!$skip_content) {
1050
+			$headers += $this->_contentHeaders();
1051
+		}
1052
+
1053
+		if (!empty($xtra_headers)) {
1054
+			$headers = array_merge($headers, $xtra_headers);
1055
+		}
1056
+
1057
+		if ($overwrite) {
1058
+			$this->_headers = array_merge($this->_headers, $headers);
1059
+		} else {
1060
+			$this->_headers = array_merge($headers, $this->_headers);
1061
+		}
1062
+
1063
+		$headers = $this->_headers;
1064
+
1065
+		if ($skip_content) {
1066
+			unset($headers['Content-Type']);
1067
+			unset($headers['Content-Transfer-Encoding']);
1068
+			unset($headers['Content-Disposition']);
1069
+		} else if (!empty($this->_build_params['ctype'])) {
1070
+			$headers['Content-Type'] = $this->_build_params['ctype'];
1071
+		}
1072
+
1073
+		$encodedHeaders = $this->_encodeHeaders($headers);
1074
+		return $encodedHeaders;
1075
+	}
1076
+
1077
+	/**
1078
+	 * Get the text version of the headers
1079
+	 * (usefull if you want to use the PHP mail() function)
1080
+	 *
1081
+	 * @param array $xtra_headers Assoc array with any extra headers (optional)
1082
+	 *                            (Don't set Content-Type for multipart messages here!)
1083
+	 * @param bool  $overwrite    Overwrite the existing headers with new.
1084
+	 * @param bool  $skip_content Don't return content headers: Content-Type,
1085
+	 *                            Content-Disposition and Content-Transfer-Encoding
1086
+	 *
1087
+	 * @return string             Plain text headers
1088
+	 * @access public
1089
+	 */
1090
+	function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false)
1091
+	{
1092
+		$headers = $this->headers($xtra_headers, $overwrite, $skip_content);
1093
+
1094
+		// Place Received: headers at the beginning of the message
1095
+		// Spam detectors often flag messages with it after the Subject: as spam
1096
+		if (isset($headers['Received'])) {
1097
+			$received = $headers['Received'];
1098
+			unset($headers['Received']);
1099
+			$headers = array('Received' => $received) + $headers;
1100
+		}
1101
+
1102
+		$ret = '';
1103
+		$eol = $this->_build_params['eol'];
1104
+
1105
+		foreach ($headers as $key => $val) {
1106
+			if (is_array($val)) {
1107
+				foreach ($val as $value) {
1108
+					$ret .= "$key: $value" . $eol;
1109
+				}
1110
+			} else {
1111
+				$ret .= "$key: $val" . $eol;
1112
+			}
1113
+		}
1114
+
1115
+		return $ret;
1116
+	}
1117
+
1118
+	/**
1119
+	 * Sets message Content-Type header.
1120
+	 * Use it to build messages with various content-types e.g. miltipart/raport
1121
+	 * not supported by _contentHeaders() function.
1122
+	 *
1123
+	 * @param string $type   Type name
1124
+	 * @param array  $params Hash array of header parameters
1125
+	 *
1126
+	 * @return void
1127
+	 * @access public
1128
+	 * @since 1.7.0
1129
+	 */
1130
+	function setContentType($type, $params = array())
1131
+	{
1132
+		$header = $type;
1133
+
1134
+		$eol = !empty($this->_build_params['eol'])
1135
+			? $this->_build_params['eol'] : "\r\n";
1136
+
1137
+		// add parameters
1138
+		$token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D'
1139
+			. '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#';
1140
+		if (is_array($params)) {
1141
+			foreach ($params as $name => $value) {
1142
+				if ($name == 'boundary') {
1143
+					$this->_build_params['boundary'] = $value;
1144
+				}
1145
+				if (!preg_match($token_regexp, $value)) {
1146
+					$header .= ";$eol $name=$value";
1147
+				} else {
1148
+					$value = addcslashes($value, '\\"');
1149
+					$header .= ";$eol $name=\"$value\"";
1150
+				}
1151
+			}
1152
+		}
1153
+
1154
+		// add required boundary parameter if not defined
1155
+		if (preg_match('/^multipart\//i', $type)) {
1156
+			if (empty($this->_build_params['boundary'])) {
1157
+				$this->_build_params['boundary'] = '=_' . md5(rand() . microtime());
1158
+			}
1159
+
1160
+			$header .= ";$eol boundary=\"".$this->_build_params['boundary']."\"";
1161
+		}
1162
+
1163
+		$this->_build_params['ctype'] = $header;
1164
+	}
1165
+
1166
+	/**
1167
+	 * Sets the Subject header
1168
+	 *
1169
+	 * @param string $subject String to set the subject to.
1170
+	 *
1171
+	 * @return void
1172
+	 * @access public
1173
+	 */
1174
+	function setSubject($subject)
1175
+	{
1176
+		$this->_headers['Subject'] = $subject;
1177
+	}
1178
+
1179
+	/**
1180
+	 * Set an email to the From (the sender) header
1181
+	 *
1182
+	 * @param string $email The email address to use
1183
+	 *
1184
+	 * @return void
1185
+	 * @access public
1186
+	 */
1187
+	function setFrom($email)
1188
+	{
1189
+		$this->_headers['From'] = $email;
1190
+	}
1191
+
1192
+	/**
1193
+	 * Add an email to the To header
1194
+	 * (multiple calls to this method are allowed)
1195
+	 *
1196
+	 * @param string $email The email direction to add
1197
+	 *
1198
+	 * @return void
1199
+	 * @access public
1200
+	 */
1201
+	function addTo($email)
1202
+	{
1203
+		if (isset($this->_headers['To'])) {
1204
+			$this->_headers['To'] .= ", $email";
1205
+		} else {
1206
+			$this->_headers['To'] = $email;
1207
+		}
1208
+	}
1209
+
1210
+	/**
1211
+	 * Add an email to the Cc (carbon copy) header
1212
+	 * (multiple calls to this method are allowed)
1213
+	 *
1214
+	 * @param string $email The email direction to add
1215
+	 *
1216
+	 * @return void
1217
+	 * @access public
1218
+	 */
1219
+	function addCc($email)
1220
+	{
1221
+		if (isset($this->_headers['Cc'])) {
1222
+			$this->_headers['Cc'] .= ", $email";
1223
+		} else {
1224
+			$this->_headers['Cc'] = $email;
1225
+		}
1226
+	}
1227
+
1228
+	/**
1229
+	 * Add an email to the Bcc (blank carbon copy) header
1230
+	 * (multiple calls to this method are allowed)
1231
+	 *
1232
+	 * @param string $email The email direction to add
1233
+	 *
1234
+	 * @return void
1235
+	 * @access public
1236
+	 */
1237
+	function addBcc($email)
1238
+	{
1239
+		if (isset($this->_headers['Bcc'])) {
1240
+			$this->_headers['Bcc'] .= ", $email";
1241
+		} else {
1242
+			$this->_headers['Bcc'] = $email;
1243
+		}
1244
+	}
1245
+
1246
+	/**
1247
+	 * Since the PHP send function requires you to specify
1248
+	 * recipients (To: header) separately from the other
1249
+	 * headers, the To: header is not properly encoded.
1250
+	 * To fix this, you can use this public method to 
1251
+	 * encode your recipients before sending to the send
1252
+	 * function
1253
+	 *
1254
+	 * @param string $recipients A comma-delimited list of recipients
1255
+	 *
1256
+	 * @return string            Encoded data
1257
+	 * @access public
1258
+	 */
1259
+	function encodeRecipients($recipients)
1260
+	{
1261
+		$input = array("To" => $recipients);
1262
+		$retval = $this->_encodeHeaders($input);
1263
+		return $retval["To"] ;
1264
+	}
1265
+
1266
+	/**
1267
+	 * Encodes headers as per RFC2047
1268
+	 *
1269
+	 * @param array $input  The header data to encode
1270
+	 * @param array $params Extra build parameters
1271
+	 *
1272
+	 * @return array        Encoded data
1273
+	 * @access private
1274
+	 */
1275
+	function _encodeHeaders($input, $params = array())
1276
+	{
1277
+		$build_params = $this->_build_params;
1278
+		while (list($key, $value) = each($params)) {
1279
+			$build_params[$key] = $value;
1280
+		}
1281
+
1282
+		foreach ($input as $hdr_name => $hdr_value) {
1283
+			if (is_array($hdr_value)) {
1284
+				foreach ($hdr_value as $idx => $value) {
1285
+					$input[$hdr_name][$idx] = $this->encodeHeader(
1286
+						$hdr_name, $value,
1287
+						$build_params['head_charset'], $build_params['head_encoding']
1288
+					);
1289
+				}
1290
+			} else {
1291
+				$input[$hdr_name] = $this->encodeHeader(
1292
+					$hdr_name, $hdr_value,
1293
+					$build_params['head_charset'], $build_params['head_encoding']
1294
+				);
1295
+			}
1296
+		}
1297
+
1298
+		return $input;
1299
+	}
1300
+
1301
+	/**
1302
+	 * Encodes a header as per RFC2047
1303
+	 *
1304
+	 * @param string $name     The header name
1305
+	 * @param string $value    The header data to encode
1306
+	 * @param string $charset  Character set name
1307
+	 * @param string $encoding Encoding name (base64 or quoted-printable)
1308
+	 *
1309
+	 * @return string          Encoded header data (without a name)
1310
+	 * @access public
1311
+	 * @since 1.5.3
1312
+	 */
1313
+	function encodeHeader($name, $value, $charset, $encoding)
1314
+	{
1315
+		$mime_part = new Mail_mimePart;
1316
+		return $mime_part->encodeHeader(
1317
+			$name, $value, $charset, $encoding, $this->_build_params['eol']
1318
+		);
1319
+	}
1320
+
1321
+	/**
1322
+	 * Get file's basename (locale independent) 
1323
+	 *
1324
+	 * @param string $filename Filename
1325
+	 *
1326
+	 * @return string          Basename
1327
+	 * @access private
1328
+	 */
1329
+	function _basename($filename)
1330
+	{
1331
+		// basename() is not unicode safe and locale dependent
1332
+		if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
1333
+			return preg_replace('/^.*[\\\\\\/]/', '', $filename);
1334
+		} else {
1335
+			return preg_replace('/^.*[\/]/', '', $filename);
1336
+		}
1337
+	}
1338
+
1339
+	/**
1340
+	 * Get Content-Type and Content-Transfer-Encoding headers of the message
1341
+	 *
1342
+	 * @return array Headers array
1343
+	 * @access private
1344
+	 */
1345
+	function _contentHeaders()
1346
+	{
1347
+		$attachments = count($this->_parts)                 ? true : false;
1348
+		$html_images = count($this->_html_images)           ? true : false;
1349
+		$html        = strlen($this->_htmlbody)             ? true : false;
1350
+		$text        = (!$html && strlen($this->_txtbody))  ? true : false;
1351
+		$headers     = array();
1352
+
1353
+		// See get()
1354
+		switch (true) {
1355
+		case $text && !$attachments:
1356
+			$headers['Content-Type'] = 'text/plain';
1357
+			break;
1358
+
1359
+		case !$text && !$html && $attachments:
1360
+		case $text && $attachments:
1361
+		case $html && $attachments && !$html_images:
1362
+		case $html && $attachments && $html_images:
1363
+			$headers['Content-Type'] = 'multipart/mixed';
1364
+			break;
1365
+
1366
+		case $html && !$attachments && !$html_images && isset($this->_txtbody):
1367
+		case $html && !$attachments && $html_images && isset($this->_txtbody):
1368
+			$headers['Content-Type'] = 'multipart/alternative';
1369
+			break;
1370
+
1371
+		case $html && !$attachments && !$html_images && !isset($this->_txtbody):
1372
+			$headers['Content-Type'] = 'text/html';
1373
+			break;
1374
+
1375
+		case $html && !$attachments && $html_images && !isset($this->_txtbody):
1376
+			$headers['Content-Type'] = 'multipart/related';
1377
+			break;
1378
+
1379
+		default:
1380
+			return $headers;
1381
+		}
1382
+
1383
+		$this->_checkParams();
1384
+
1385
+		$eol = !empty($this->_build_params['eol'])
1386
+			? $this->_build_params['eol'] : "\r\n";
1387
+
1388
+		if ($headers['Content-Type'] == 'text/plain') {
1389
+			// single-part message: add charset and encoding
1390
+			$charset = 'charset=' . $this->_build_params['text_charset'];
1391
+			// place charset parameter in the same line, if possible
1392
+			// 26 = strlen("Content-Type: text/plain; ")
1393
+			$headers['Content-Type']
1394
+				.= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset";
1395
+			$headers['Content-Transfer-Encoding']
1396
+				= $this->_build_params['text_encoding'];
1397
+		} else if ($headers['Content-Type'] == 'text/html') {
1398
+			// single-part message: add charset and encoding
1399
+			$charset = 'charset=' . $this->_build_params['html_charset'];
1400
+			// place charset parameter in the same line, if possible
1401
+			$headers['Content-Type']
1402
+				.= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset";
1403
+			$headers['Content-Transfer-Encoding']
1404
+				= $this->_build_params['html_encoding'];
1405
+		} else {
1406
+			// multipart message: and boundary
1407
+			if (!empty($this->_build_params['boundary'])) {
1408
+				$boundary = $this->_build_params['boundary'];
1409
+			} else if (!empty($this->_headers['Content-Type'])
1410
+				&& preg_match('/boundary="([^"]+)"/', $this->_headers['Content-Type'], $m)
1411
+			) {
1412
+				$boundary = $m[1];
1413
+			} else {
1414
+				$boundary = '=_' . md5(rand() . microtime());
1415
+			}
1416
+
1417
+			$this->_build_params['boundary'] = $boundary;
1418
+			$headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
1419
+		}
1420
+
1421
+		return $headers;
1422
+	}
1423
+
1424
+	/**
1425
+	 * Validate and set build parameters
1426
+	 *
1427
+	 * @return void
1428
+	 * @access private
1429
+	 */
1430
+	function _checkParams()
1431
+	{
1432
+		$encodings = array('7bit', '8bit', 'base64', 'quoted-printable');
1433
+
1434
+		$this->_build_params['text_encoding']
1435
+			= strtolower($this->_build_params['text_encoding']);
1436
+		$this->_build_params['html_encoding']
1437
+			= strtolower($this->_build_params['html_encoding']);
1438
+
1439
+		if (!in_array($this->_build_params['text_encoding'], $encodings)) {
1440
+			$this->_build_params['text_encoding'] = '7bit';
1441
+		}
1442
+		if (!in_array($this->_build_params['html_encoding'], $encodings)) {
1443
+			$this->_build_params['html_encoding'] = '7bit';
1444
+		}
1445
+
1446
+		// text body
1447
+		if ($this->_build_params['text_encoding'] == '7bit'
1448
+			&& !preg_match('/ascii/i', $this->_build_params['text_charset'])
1449
+			&& preg_match('/[^\x00-\x7F]/', $this->_txtbody)
1450
+		) {
1451
+			$this->_build_params['text_encoding'] = 'quoted-printable';
1452
+		}
1453
+		// html body
1454
+		if ($this->_build_params['html_encoding'] == '7bit'
1455
+			&& !preg_match('/ascii/i', $this->_build_params['html_charset'])
1456
+			&& preg_match('/[^\x00-\x7F]/', $this->_htmlbody)
1457
+		) {
1458
+			$this->_build_params['html_encoding'] = 'quoted-printable';
1459
+		}
1460
+	}
1461
+
1462
+	/**
1463
+	 * PEAR::isError implementation
1464
+	 *
1465
+	 * @param mixed $data Object
1466
+	 *
1467
+	 * @return bool True if object is an instance of PEAR_Error
1468
+	 * @access private
1469
+	 */
1470
+	function _isError($data)
1471
+	{
1472
+		// PEAR::isError() is not PHP 5.4 compatible (see Bug #19473)
1473
+		if (is_object($data) && is_a($data, 'PEAR_Error')) {
1474
+			return true;
1475
+		}
1476
+
1477
+		return false;
1478
+	}
1479
+
1480
+	/**
1481
+	 * PEAR::raiseError implementation
1482
+	 *
1483
+	 * @param $message A text error message
1484
+	 *
1485
+	 * @return PEAR_Error Instance of PEAR_Error
1486
+	 * @access private
1487
+	 */
1488
+	function _raiseError($message)
1489
+	{
1490
+		// PEAR::raiseError() is not PHP 5.4 compatible
1491
+		return new PEAR_Error($message);
1492
+	}
1493 1493
 
1494 1494
 } // End of class
Please login to merge, or discard this patch.