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