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