[BUGFIX] Some methods in t3lib_TSparser should be static
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_svbase.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the Typo3 project. The Typo3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Parent class for "Services" classes
29 *
30 * TODO: temp files are not removed
31 *
32 * @author René Fritz <r.fritz@colorcube.de>
33 */
34
35
36 define ('T3_ERR_SV_GENERAL', -1); // General error - something went wrong
37 define ('T3_ERR_SV_NOT_AVAIL', -2); // During execution it showed that the service is not available and should be ignored. The service itself should call $this->setNonAvailable()
38 define ('T3_ERR_SV_WRONG_SUBTYPE', -3); // passed subtype is not possible with this service
39 define ('T3_ERR_SV_NO_INPUT', -4); // passed subtype is not possible with this service
40
41
42 define ('T3_ERR_SV_FILE_NOT_FOUND', -20); // File not found which the service should process
43 define ('T3_ERR_SV_FILE_READ', -21); // File not readable
44 define ('T3_ERR_SV_FILE_WRITE', -22); // File not writable
45
46 define ('T3_ERR_SV_PROG_NOT_FOUND', -40); // passed subtype is not possible with this service
47 define ('T3_ERR_SV_PROG_FAILED', -41); // passed subtype is not possible with this service
48
49 // define ('T3_ERR_SV_serviceType_myerr, -100); // All errors with prefix T3_ERR_SV_[serviceType]_ and lower than -99 are service type dependent error
50
51
52 /**
53 * Parent class for "Services" classes
54 *
55 * @author René Fritz <r.fritz@colorcube.de>
56 * @package TYPO3
57 * @subpackage t3lib
58 */
59 abstract class t3lib_svbase {
60
61 /**
62 * @var array service description array
63 */
64 var $info = array();
65
66 /**
67 * @var array error stack
68 */
69 var $error = array();
70
71 /**
72 * @var bool Defines if debug messages should be written with t3lib_div::devLog
73 */
74 var $writeDevLog = FALSE;
75
76
77 /**
78 * @var string The output content. That's what the services produced as result.
79 */
80 var $out = '';
81
82 /**
83 * @var string The file that should be processed.
84 */
85 var $inputFile = '';
86
87 /**
88 * @var string The content that should be processed.
89 */
90 var $inputContent = '';
91
92 /**
93 * @var string The type of the input content (or file). Might be the same as the service subtypes.
94 */
95 var $inputType = '';
96
97 /**
98 * @var string The file where the output should be written to.
99 */
100 var $outputFile = '';
101
102
103 /**
104 * Temporary files which have to be deleted
105 *
106 * @private
107 */
108 var $tempFiles = array();
109
110 /** @var string Prefix for temporary files */
111 protected $prefixId = '';
112
113 /***************************************
114 *
115 * Get service meta information
116 *
117 ***************************************/
118
119
120 /**
121 * Returns internal information array for service
122 *
123 * @return array service description array
124 */
125 function getServiceInfo() {
126 return $this->info;
127 }
128
129
130 /**
131 * Returns the service key of the service
132 *
133 * @return string service key
134 */
135 function getServiceKey() {
136 return $this->info['serviceKey'];
137 }
138
139
140 /**
141 * Returns the title of the service
142 *
143 * @return string service title
144 */
145 function getServiceTitle() {
146 return $this->info['title'];
147 }
148
149
150 /**
151 * Returns service configuration values from the $TYPO3_CONF_VARS['SVCONF'] array
152 *
153 * @param string Name of the config option
154 * @param mixed Default configuration if no special config is available
155 * @param bool If set the 'default' config will be returned if no special config for this service is available (default: TRUE)
156 * @return mixed configuration value for the service
157 */
158 function getServiceOption($optionName, $defaultValue = '', $includeDefaultConfig = TRUE) {
159 $config = NULL;
160
161 $svOptions = $GLOBALS['TYPO3_CONF_VARS']['SVCONF'][$this->info['serviceType']];
162
163 if (isset($svOptions[$this->info['serviceKey']][$optionName])) {
164 $config = $svOptions[$this->info['serviceKey']][$optionName];
165 } elseif ($includeDefaultConfig && isset($svOptions['default'][$optionName])) {
166 $config = $svOptions['default'][$optionName];
167 }
168 if (!isset($config)) {
169 $config = $defaultValue;
170 }
171 return $config;
172 }
173
174
175 /***************************************
176 *
177 * Error handling
178 *
179 ***************************************/
180
181
182 /**
183 * Logs debug messages to t3lib_div::devLog()
184 *
185 * @param string Debug message
186 * @param integer Severity: 0 is info, 1 is notice, 2 is warning, 3 is fatal error, -1 is "OK" message
187 * @param array|bool Additional data you want to pass to the logger.
188 * @return void
189 */
190 function devLog($msg, $severity = 0, $dataVar = FALSE) {
191 if ($this->writeDevLog) {
192 t3lib_div::devLog($msg, $this->info['serviceKey'], $severity, $dataVar);
193 }
194 }
195
196
197 /**
198 * Puts an error on the error stack. Calling without parameter adds a general error.
199 *
200 * @param integer error number (see T3_ERR_SV_* constants)
201 * @param string error message
202 * @return void
203 */
204 function errorPush($errNum = T3_ERR_SV_GENERAL, $errMsg = 'Unspecified error occured') {
205 array_push($this->error, array('nr' => $errNum, 'msg' => $errMsg));
206
207 if (is_object($GLOBALS['TT'])) {
208 $GLOBALS['TT']->setTSlogMessage($errMsg, 2);
209 }
210
211 }
212
213
214 /**
215 * Removes the last error from the error stack.
216 *
217 * @return void
218 */
219 function errorPull() {
220 array_pop($this->error);
221
222 // pop for $GLOBALS['TT']->setTSlogMessage is not supported
223 }
224
225
226 /**
227 * Returns the last error number from the error stack.
228 *
229 * @return int|bool error number (or TRUE if no error)
230 */
231 function getLastError() {
232 $lastError = TRUE; // means all is ok - no error
233 if (count($this->error)) {
234 $error = end($this->error);
235 $lastError = $error['nr'];
236 }
237 return $lastError;
238 }
239
240
241 /**
242 * Returns the last message from the error stack.
243 *
244 * @return string error message
245 */
246 function getLastErrorMsg() {
247 $lastErrorMessage = '';
248 if (count($this->error)) {
249 $error = end($this->error);
250 $lastErrorMessage = $error['msg'];
251 }
252 return $lastErrorMessage;
253 }
254
255
256 /**
257 * Returns all error messages as array.
258 *
259 * @return array error messages
260 */
261 function getErrorMsgArray() {
262 $errArr = array();
263
264 if (count($this->error)) {
265 foreach ($this->error as $error) {
266 $errArr[] = $error['msg'];
267 }
268 }
269 return $errArr;
270 }
271
272
273 /**
274 * Returns the last array from the error stack.
275 *
276 * @return array error nr and message
277 */
278 function getLastErrorArray() {
279 return end($this->error);
280 }
281
282 /**
283 * Reset the error stack.
284 *
285 * @return void
286 */
287 function resetErrors() {
288 $this->error = array();
289 }
290
291
292 /***************************************
293 *
294 * General service functions
295 *
296 ***************************************/
297
298
299 /**
300 * check the availability of external programs
301 *
302 * @param string comma list of programs 'perl,python,pdftotext'
303 * @return boolean return FALSE if one program was not found
304 */
305 function checkExec($progList) {
306 $ret = TRUE;
307
308 $progList = t3lib_div::trimExplode(',', $progList, 1);
309 foreach ($progList as $prog) {
310 if (!t3lib_exec::checkCommand($prog)) {
311 // program not found
312 $this->errorPush(T3_ERR_SV_PROG_NOT_FOUND, 'External program not found: ' . $prog);
313 $ret = FALSE;
314 }
315 }
316 return $ret;
317 }
318
319
320 /**
321 * Deactivate the service. Use this if the service fails at runtime and will not be available.
322 *
323 * @return void
324 */
325 function deactivateService() {
326 t3lib_extMgm::deactivateService($this->info['serviceType'], $this->info['serviceKey']);
327 }
328
329
330 /***************************************
331 *
332 * IO tools
333 *
334 ***************************************/
335
336
337 /**
338 * Check if a file exists and is readable.
339 *
340 * @param string File name with absolute path.
341 * @return string|bool File name or FALSE.
342 */
343 function checkInputFile($absFile) {
344 $checkResult = FALSE;
345 if (t3lib_div::isAllowedAbsPath($absFile) && @is_file($absFile)) {
346 if (@is_readable($absFile)) {
347 $checkResult = $absFile;
348 } else {
349 $this->errorPush(T3_ERR_SV_FILE_READ, 'File is not readable: ' . $absFile);
350 }
351 } else {
352 $this->errorPush(T3_ERR_SV_FILE_NOT_FOUND, 'File not found: ' . $absFile);
353 }
354 return $checkResult;
355 }
356
357
358 /**
359 * Read content from a file a file.
360 *
361 * @param string File name to read from.
362 * @param integer Maximum length to read. If empty the whole file will be read.
363 * @return string|bool $content or FALSE
364 */
365 function readFile($absFile, $length = 0) {
366 $out = FALSE;
367
368 if ($this->checkInputFile($absFile)) {
369 $out = file_get_contents($absFile);
370 if ($out === FALSE) {
371 $this->errorPush(T3_ERR_SV_FILE_READ, 'Can not read from file: ' . $absFile);
372 }
373 }
374 return $out;
375 }
376
377
378 /**
379 * Write content to a file.
380 *
381 * @param string Content to write to the file
382 * @param string File name to write into. If empty a temp file will be created.
383 * @return string|bool File name or FALSE
384 */
385 function writeFile($content, $absFile = '') {
386 if (!$absFile) {
387 $absFile = $this->tempFile($this->prefixId);
388 }
389
390 if ($absFile && t3lib_div::isAllowedAbsPath($absFile)) {
391 if ($fd = @fopen($absFile, 'wb')) {
392 @fwrite($fd, $content);
393 @fclose($fd);
394 } else {
395 $this->errorPush(T3_ERR_SV_FILE_WRITE, 'Can not write to file: ' . $absFile);
396 $absFile = FALSE;
397 }
398 }
399
400 return $absFile;
401 }
402
403 /**
404 * Create a temporary file.
405 *
406 * @param string File prefix.
407 * @return string|bool File name or FALSE
408 */
409 function tempFile($filePrefix) {
410 $absFile = t3lib_div::tempnam($filePrefix);
411 if ($absFile) {
412 $ret = $absFile;
413 $this->registerTempFile($absFile);
414 } else {
415 $ret = FALSE;
416 $this->errorPush(T3_ERR_SV_FILE_WRITE, 'Can not create temp file.');
417 }
418 return $ret;
419 }
420
421 /**
422 * Register file which should be deleted afterwards.
423 *
424 * @param string File name with absolute path.
425 * @return void
426 */
427 function registerTempFile($absFile) {
428 $this->tempFiles[] = $absFile;
429 }
430
431 /**
432 * Delete registered temporary files.
433 *
434 * @param string File name with absolute path.
435 * @return void
436 */
437 function unlinkTempFiles() {
438 foreach ($this->tempFiles as $absFile) {
439 t3lib_div::unlink_tempfile($absFile);
440 }
441 $this->tempFiles = array();
442 }
443
444
445 /***************************************
446 *
447 * IO input
448 *
449 ***************************************/
450
451
452 /**
453 * Set the input content for service processing.
454 *
455 * @param mixed Input content (going into ->inputContent)
456 * @param string The type of the input content (or file). Might be the same as the service subtypes.
457 * @return void
458 */
459 function setInput($content, $type = '') {
460 $this->inputContent = $content;
461 $this->inputFile = '';
462 $this->inputType = $type;
463 }
464
465
466 /**
467 * Set the input file name for service processing.
468 *
469 * @param string file name
470 * @param string The type of the input content (or file). Might be the same as the service subtypes.
471 * @return void
472 */
473 function setInputFile($absFile, $type = '') {
474 $this->inputContent = '';
475 $this->inputFile = $absFile;
476 $this->inputType = $type;
477 }
478
479
480 /**
481 * Get the input content.
482 * Will be read from input file if needed. (That is if ->inputContent is empty and ->inputFile is not)
483 *
484 * @return mixed
485 */
486 function getInput() {
487 if ($this->inputContent == '') {
488 $this->inputContent = $this->readFile($this->inputFile);
489 }
490 return $this->inputContent;
491 }
492
493
494 /**
495 * Get the input file name.
496 * If the content was set by setContent a file will be created.
497 *
498 * @param string File name. If empty a temp file will be created.
499 * @return string File name or FALSE if no input or file error.
500 */
501 function getInputFile($createFile = '') {
502 if ($this->inputFile) {
503 $this->inputFile = $this->checkInputFile($this->inputFile);
504 } elseif ($this->inputContent) {
505 $this->inputFile = $this->writeFile($this->inputContent, $createFile);
506 }
507 return $this->inputFile;
508 }
509
510
511 /***************************************
512 *
513 * IO output
514 *
515 ***************************************/
516
517
518 /**
519 * Set the output file name.
520 *
521 * @param string file name
522 * @return void
523 */
524 function setOutputFile($absFile) {
525 $this->outputFile = $absFile;
526 }
527
528
529 /**
530 * Get the output content.
531 *
532 * @return mixed
533 */
534 function getOutput() {
535 if ($this->outputFile) {
536 $this->out = $this->readFile($this->outputFile);
537 }
538 return $this->out;
539 }
540
541
542 /**
543 * Get the output file name. If no output file is set, the ->out buffer is written to the file given by input parameter filename
544 *
545 * @param string Absolute filename to write to
546 * @return mixed
547 */
548 function getOutputFile($absFile = '') {
549 if (!$this->outputFile) {
550 $this->outputFile = $this->writeFile($this->out, $absFile);
551 }
552 return $this->outputFile;
553 }
554
555
556 /***************************************
557 *
558 * Service implementation
559 *
560 ***************************************/
561
562 /**
563 * Initialization of the service.
564 *
565 * The class have to do a strict check if the service is available.
566 * example: check if the perl interpreter is available which is needed to run an extern perl script.
567 *
568 * @return boolean TRUE if the service is available
569 */
570 function init() {
571 // do not work :-( but will not hurt
572 // use it as inspiration for a service based on this class
573 register_shutdown_function(array(&$this, '__destruct'));
574 // look in makeInstanceService()
575
576 $this->reset();
577
578 // check for external programs which are defined by $info['exec']
579 if (trim($this->info['exec'])) {
580 if (!$this->checkExec($this->info['exec'])) {
581 // nothing todo here or?
582 }
583 }
584
585 return ($this->getLastError() === TRUE);
586 }
587
588
589 /**
590 * Resets the service.
591 * Will be called by init(). Should be used before every use if a service instance is used multiple times.
592 *
593 * @return void
594 */
595 function reset() {
596 $this->unlinkTempFiles();
597 $this->resetErrors();
598 $this->out = '';
599 $this->inputFile = '';
600 $this->inputContent = '';
601 $this->inputType = '';
602 $this->outputFile = '';
603 }
604
605 /**
606 * Clean up the service.
607 * Child classes should explicitly call parent::__destruct() in their destructors for this to work
608 *
609 * @return void
610 */
611 function __destruct() {
612 $this->unlinkTempFiles();
613 }
614
615 }
616
617 // XCLASS handling does not make sense, because this class is always extended by the service classes..
618 ?>