@@ -388,10 +388,10 @@ discard block |
||
388 | 388 | * Important: PHP 5.0 introduced a bug that wasn't fixed until 5.1: the return value has to be the oposite! |
389 | 389 | * |
390 | 390 | * if(version_compare(PHP_VERSION,'5.0','>=') && version_compare(PHP_VERSION,'5.1','<')) |
391 | - * { |
|
391 | + * { |
|
392 | 392 | * $eof = !$eof; |
393 | 393 | * } |
394 | - * |
|
394 | + * |
|
395 | 395 | * @return boolean true if the read/write position is at the end of the stream and no more data availible, false otherwise |
396 | 396 | */ |
397 | 397 | function stream_eof ( ) |
@@ -1010,7 +1010,7 @@ discard block |
||
1010 | 1010 | if (self::LOG_LEVEL > 1) error_log(__METHOD__."('$path',$flags,'$url'): ".function_backtrace(1)); |
1011 | 1011 | |
1012 | 1012 | while (($rel_path = egw_vfs::basename($url).($rel_path ? '/'.$rel_path : '')) && |
1013 | - ($url = egw_vfs::dirname($url))) |
|
1013 | + ($url = egw_vfs::dirname($url))) |
|
1014 | 1014 | { |
1015 | 1015 | if (($stat = self::url_stat($url,0,false,false))) |
1016 | 1016 | { |
@@ -112,16 +112,16 @@ discard block |
||
112 | 112 | } |
113 | 113 | |
114 | 114 | /** |
115 | - * Created an input-field with an attached color-picker |
|
116 | - * |
|
117 | - * Please note: it need to be called before the call to egw_header() !!! |
|
118 | - * |
|
119 | - * @param string $name the name of the input-field |
|
120 | - * @param string $value ='' the actual value for the input-field, default '' |
|
121 | - * @param string $title ='' tooltip/title for the picker-activation-icon |
|
122 | - * @param string $options ='' options for input |
|
123 | - * @return string the html |
|
124 | - */ |
|
115 | + * Created an input-field with an attached color-picker |
|
116 | + * |
|
117 | + * Please note: it need to be called before the call to egw_header() !!! |
|
118 | + * |
|
119 | + * @param string $name the name of the input-field |
|
120 | + * @param string $value ='' the actual value for the input-field, default '' |
|
121 | + * @param string $title ='' tooltip/title for the picker-activation-icon |
|
122 | + * @param string $options ='' options for input |
|
123 | + * @return string the html |
|
124 | + */ |
|
125 | 125 | static function inputColor($name,$value='',$title='',$options='') |
126 | 126 | { |
127 | 127 | $options .= ' id="'.htmlspecialchars($id=str_replace(array('[',']'),array('_',''),$name).'_colorpicker').'"'; |
@@ -137,16 +137,16 @@ discard block |
||
137 | 137 | } |
138 | 138 | |
139 | 139 | /** |
140 | - * Handles tooltips via the wz_tooltip class from Walter Zorn |
|
141 | - * |
|
142 | - * @param string $text text or html for the tooltip, all chars allowed, they will be quoted approperiate |
|
143 | - * @param boolean $do_lang (default False) should the text be run though lang() |
|
144 | - * @param array $options param/value pairs, eg. 'TITLE' => 'I am the title'. Some common parameters: |
|
145 | - * title (string) gives extra title-row, width (int,'auto') , padding (int), above (bool), bgcolor (color), bgimg (URL) |
|
146 | - * For a complete list and description see http://www.walterzorn.com/tooltip/tooltip_e.htm |
|
147 | - * @param boolean $return_as_attributes true to return array(onmouseover, onmouseout) attributes |
|
148 | - * @return string|array to be included in any tag, like '<p'.html::tooltip('Hello <b>Ralf</b>').'>Text with tooltip</p>' |
|
149 | - */ |
|
140 | + * Handles tooltips via the wz_tooltip class from Walter Zorn |
|
141 | + * |
|
142 | + * @param string $text text or html for the tooltip, all chars allowed, they will be quoted approperiate |
|
143 | + * @param boolean $do_lang (default False) should the text be run though lang() |
|
144 | + * @param array $options param/value pairs, eg. 'TITLE' => 'I am the title'. Some common parameters: |
|
145 | + * title (string) gives extra title-row, width (int,'auto') , padding (int), above (bool), bgcolor (color), bgimg (URL) |
|
146 | + * For a complete list and description see http://www.walterzorn.com/tooltip/tooltip_e.htm |
|
147 | + * @param boolean $return_as_attributes true to return array(onmouseover, onmouseout) attributes |
|
148 | + * @return string|array to be included in any tag, like '<p'.html::tooltip('Hello <b>Ralf</b>').'>Text with tooltip</p>' |
|
149 | + */ |
|
150 | 150 | static function tooltip($text,$do_lang=False,$options=False, $return_as_attributes=false) |
151 | 151 | { |
152 | 152 | // tell egw_framework to include wz_tooltip.js |
@@ -594,20 +594,20 @@ discard block |
||
594 | 594 | } |
595 | 595 | |
596 | 596 | /** |
597 | - * this static function is a wrapper for fckEditor to create some reuseable layouts |
|
598 | - * |
|
599 | - * @param string $_name name and id of the input-field |
|
600 | - * @param string $_content of the tinymce (will be run through htmlspecialchars !!!), default '' |
|
601 | - * @param string $_mode display mode of the tinymce editor can be: simple, extended or advanced |
|
602 | - * @param array $_options (toolbar_expanded true/false) |
|
603 | - * @param string $_height ='400px' |
|
604 | - * @param string $_width ='100%' |
|
605 | - * @param string $_start_path ='' if passed activates the browser for image at absolute path passed |
|
606 | - * @param boolean $_purify =true run $_content through htmlpurifier before handing it to fckEditor |
|
607 | - * @param mixed (boolean/string) $_focusToBody=false USED only for CKEDIOR true means yes, focus on top, you may specify TOP or BOTTOM (to focus on the end of the editor area) |
|
608 | - * @param string $_executeJSAfterInit ='' Javascript to be executed after InstanceReady of CKEditor |
|
609 | - * @return string the necessary html for the textarea |
|
610 | - */ |
|
597 | + * this static function is a wrapper for fckEditor to create some reuseable layouts |
|
598 | + * |
|
599 | + * @param string $_name name and id of the input-field |
|
600 | + * @param string $_content of the tinymce (will be run through htmlspecialchars !!!), default '' |
|
601 | + * @param string $_mode display mode of the tinymce editor can be: simple, extended or advanced |
|
602 | + * @param array $_options (toolbar_expanded true/false) |
|
603 | + * @param string $_height ='400px' |
|
604 | + * @param string $_width ='100%' |
|
605 | + * @param string $_start_path ='' if passed activates the browser for image at absolute path passed |
|
606 | + * @param boolean $_purify =true run $_content through htmlpurifier before handing it to fckEditor |
|
607 | + * @param mixed (boolean/string) $_focusToBody=false USED only for CKEDIOR true means yes, focus on top, you may specify TOP or BOTTOM (to focus on the end of the editor area) |
|
608 | + * @param string $_executeJSAfterInit ='' Javascript to be executed after InstanceReady of CKEditor |
|
609 | + * @return string the necessary html for the textarea |
|
610 | + */ |
|
611 | 611 | static function fckEditor($_name, $_content, $_mode, $_options=array('toolbar_expanded' =>'true'), |
612 | 612 | $_height='400px', $_width='100%',$_start_path='',$_purify=true, $_focusToBody=false, $_executeJSAfterInit='') |
613 | 613 | { |
@@ -678,21 +678,21 @@ discard block |
||
678 | 678 | } |
679 | 679 | |
680 | 680 | /** |
681 | - * this static function is a wrapper for tinymce to create some reuseable layouts |
|
682 | - * |
|
683 | - * Please note: if you did not run init_tinymce already you this static function need to be called before the call to phpgw_header() !!! |
|
684 | - * |
|
685 | - * @param string $_name name and id of the input-field |
|
686 | - * @param string $_mode display mode of the tinymce editor can be: simple, extended or advanced |
|
687 | - * @param string $_content ='' of the tinymce (will be run through htmlspecialchars !!!), default '' |
|
688 | - * @param string $_height ='400px' |
|
689 | - * @param string $_width ='100%' |
|
690 | - * @param boolean $_purify =true |
|
691 | - * @param string $_border ='0px' NOT used for CKEditor |
|
692 | - * @param mixed (boolean/string) $_focusToBody=false USED only for CKEDIOR true means yes, focus on top, you may specify TOP or BOTTOM (to focus on the end of the editor area) |
|
693 | - * @param string $_executeJSAfterInit ='' Javascript to be executed after InstanceReady of CKEditor |
|
694 | - * @return string the necessary html for the textarea |
|
695 | - */ |
|
681 | + * this static function is a wrapper for tinymce to create some reuseable layouts |
|
682 | + * |
|
683 | + * Please note: if you did not run init_tinymce already you this static function need to be called before the call to phpgw_header() !!! |
|
684 | + * |
|
685 | + * @param string $_name name and id of the input-field |
|
686 | + * @param string $_mode display mode of the tinymce editor can be: simple, extended or advanced |
|
687 | + * @param string $_content ='' of the tinymce (will be run through htmlspecialchars !!!), default '' |
|
688 | + * @param string $_height ='400px' |
|
689 | + * @param string $_width ='100%' |
|
690 | + * @param boolean $_purify =true |
|
691 | + * @param string $_border ='0px' NOT used for CKEditor |
|
692 | + * @param mixed (boolean/string) $_focusToBody=false USED only for CKEDIOR true means yes, focus on top, you may specify TOP or BOTTOM (to focus on the end of the editor area) |
|
693 | + * @param string $_executeJSAfterInit ='' Javascript to be executed after InstanceReady of CKEditor |
|
694 | + * @return string the necessary html for the textarea |
|
695 | + */ |
|
696 | 696 | static function fckEditorQuick($_name, $_mode, $_content='', $_height='400px', $_width='100%',$_purify=true, $_border='0px',$_focusToBody=false,$_executeJSAfterInit='') |
697 | 697 | { |
698 | 698 | if (!self::htmlarea_availible() || $_mode == 'ascii') |
@@ -962,7 +962,7 @@ |
||
962 | 962 | 'account_fullname' => 'cn', |
963 | 963 | ); |
964 | 964 | if (!isset($to_ldap[$which]) || $account_type === 'g') { |
965 | - return False; |
|
965 | + return False; |
|
966 | 966 | } |
967 | 967 | |
968 | 968 | $sri = ldap_search($this->ds, $this->user_context, '(&('.$to_ldap[$which].'=' . $name . ')(objectclass=posixaccount))', array('uidNumber')); |
@@ -27,17 +27,17 @@ |
||
27 | 27 | class ldap |
28 | 28 | { |
29 | 29 | /** |
30 | - * Holds the LDAP link identifier |
|
31 | - * |
|
32 | - * @var resource $ds |
|
33 | - */ |
|
30 | + * Holds the LDAP link identifier |
|
31 | + * |
|
32 | + * @var resource $ds |
|
33 | + */ |
|
34 | 34 | var $ds; |
35 | 35 | |
36 | 36 | /** |
37 | - * Holds the detected information about the connected ldap server |
|
38 | - * |
|
39 | - * @var ldapserverinfo $ldapserverinfo |
|
40 | - */ |
|
37 | + * Holds the detected information about the connected ldap server |
|
38 | + * |
|
39 | + * @var ldapserverinfo $ldapserverinfo |
|
40 | + */ |
|
41 | 41 | var $ldapServerInfo; |
42 | 42 | |
43 | 43 | /** |
@@ -286,7 +286,7 @@ |
||
286 | 286 | $short = translation::translate($m=substr($name,0,3), null, '*'); // test if our lang-file have a translation for the english short with 3 chars |
287 | 287 | if ($substr($short,-1) == '*') // else create one by truncating the full translation to x chars |
288 | 288 | { |
289 | - $short = $chars_shortcut > 0 ? $substr(lang($name),0,$chars_shortcut) : $substr(lang($name),$chars_shortcut); |
|
289 | + $short = $chars_shortcut > 0 ? $substr(lang($name),0,$chars_shortcut) : $substr(lang($name),$chars_shortcut); |
|
290 | 290 | } |
291 | 291 | echo "\n \"".$short.'"'.($n < 11 ? ',' : ''); |
292 | 292 | } |
@@ -28,64 +28,64 @@ |
||
28 | 28 | */ |
29 | 29 | class Minify_Controller_Groups extends Minify_Controller_Base { |
30 | 30 | |
31 | - /** |
|
32 | - * Set up groups of files as sources |
|
33 | - * |
|
34 | - * @param array $options controller and Minify options |
|
35 | - * |
|
36 | - * 'groups': (required) array mapping PATH_INFO strings to arrays |
|
37 | - * of complete file paths. @see Minify_Controller_Groups |
|
38 | - * |
|
39 | - * @return array Minify options |
|
40 | - */ |
|
41 | - public function setupSources($options) { |
|
42 | - // strip controller options |
|
43 | - $groups = $options['groups']; |
|
44 | - unset($options['groups']); |
|
31 | + /** |
|
32 | + * Set up groups of files as sources |
|
33 | + * |
|
34 | + * @param array $options controller and Minify options |
|
35 | + * |
|
36 | + * 'groups': (required) array mapping PATH_INFO strings to arrays |
|
37 | + * of complete file paths. @see Minify_Controller_Groups |
|
38 | + * |
|
39 | + * @return array Minify options |
|
40 | + */ |
|
41 | + public function setupSources($options) { |
|
42 | + // strip controller options |
|
43 | + $groups = $options['groups']; |
|
44 | + unset($options['groups']); |
|
45 | 45 | |
46 | - // mod_fcgid places PATH_INFO in ORIG_PATH_INFO |
|
47 | - $pi = isset($_SERVER['ORIG_PATH_INFO']) |
|
48 | - ? substr($_SERVER['ORIG_PATH_INFO'], 1) |
|
49 | - : (isset($_SERVER['PATH_INFO']) |
|
50 | - ? substr($_SERVER['PATH_INFO'], 1) |
|
51 | - : false |
|
52 | - ); |
|
53 | - if (false === $pi || ! isset($groups[$pi])) { |
|
54 | - // no PATH_INFO or not a valid group |
|
55 | - $this->log("Missing PATH_INFO or no group set for \"$pi\""); |
|
56 | - return $options; |
|
57 | - } |
|
58 | - $sources = array(); |
|
46 | + // mod_fcgid places PATH_INFO in ORIG_PATH_INFO |
|
47 | + $pi = isset($_SERVER['ORIG_PATH_INFO']) |
|
48 | + ? substr($_SERVER['ORIG_PATH_INFO'], 1) |
|
49 | + : (isset($_SERVER['PATH_INFO']) |
|
50 | + ? substr($_SERVER['PATH_INFO'], 1) |
|
51 | + : false |
|
52 | + ); |
|
53 | + if (false === $pi || ! isset($groups[$pi])) { |
|
54 | + // no PATH_INFO or not a valid group |
|
55 | + $this->log("Missing PATH_INFO or no group set for \"$pi\""); |
|
56 | + return $options; |
|
57 | + } |
|
58 | + $sources = array(); |
|
59 | 59 | |
60 | - $files = $groups[$pi]; |
|
61 | - // if $files is a single object, casting will break it |
|
62 | - if (is_object($files)) { |
|
63 | - $files = array($files); |
|
64 | - } elseif (! is_array($files)) { |
|
65 | - $files = (array)$files; |
|
66 | - } |
|
67 | - foreach ($files as $file) { |
|
68 | - if ($file instanceof Minify_Source) { |
|
69 | - $sources[] = $file; |
|
70 | - continue; |
|
71 | - } |
|
72 | - if (0 === strpos($file, '//')) { |
|
73 | - $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1); |
|
74 | - } |
|
75 | - $realPath = realpath($file); |
|
76 | - if (is_file($realPath)) { |
|
77 | - $sources[] = new Minify_Source(array( |
|
78 | - 'filepath' => $realPath |
|
79 | - )); |
|
80 | - } else { |
|
81 | - $this->log("The path \"{$file}\" could not be found (or was not a file)"); |
|
82 | - return $options; |
|
83 | - } |
|
84 | - } |
|
85 | - if ($sources) { |
|
86 | - $this->sources = $sources; |
|
87 | - } |
|
88 | - return $options; |
|
89 | - } |
|
60 | + $files = $groups[$pi]; |
|
61 | + // if $files is a single object, casting will break it |
|
62 | + if (is_object($files)) { |
|
63 | + $files = array($files); |
|
64 | + } elseif (! is_array($files)) { |
|
65 | + $files = (array)$files; |
|
66 | + } |
|
67 | + foreach ($files as $file) { |
|
68 | + if ($file instanceof Minify_Source) { |
|
69 | + $sources[] = $file; |
|
70 | + continue; |
|
71 | + } |
|
72 | + if (0 === strpos($file, '//')) { |
|
73 | + $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1); |
|
74 | + } |
|
75 | + $realPath = realpath($file); |
|
76 | + if (is_file($realPath)) { |
|
77 | + $sources[] = new Minify_Source(array( |
|
78 | + 'filepath' => $realPath |
|
79 | + )); |
|
80 | + } else { |
|
81 | + $this->log("The path \"{$file}\" could not be found (or was not a file)"); |
|
82 | + return $options; |
|
83 | + } |
|
84 | + } |
|
85 | + if ($sources) { |
|
86 | + $this->sources = $sources; |
|
87 | + } |
|
88 | + return $options; |
|
89 | + } |
|
90 | 90 | } |
91 | 91 |
@@ -16,207 +16,207 @@ |
||
16 | 16 | */ |
17 | 17 | abstract class Minify_Controller_Base { |
18 | 18 | |
19 | - /** |
|
20 | - * Setup controller sources and set an needed options for Minify::source |
|
21 | - * |
|
22 | - * You must override this method in your subclass controller to set |
|
23 | - * $this->sources. If the request is NOT valid, make sure $this->sources |
|
24 | - * is left an empty array. Then strip any controller-specific options from |
|
25 | - * $options and return it. To serve files, $this->sources must be an array of |
|
26 | - * Minify_Source objects. |
|
27 | - * |
|
28 | - * @param array $options controller and Minify options |
|
29 | - * |
|
30 | - * @return array $options Minify::serve options |
|
31 | - */ |
|
32 | - abstract public function setupSources($options); |
|
19 | + /** |
|
20 | + * Setup controller sources and set an needed options for Minify::source |
|
21 | + * |
|
22 | + * You must override this method in your subclass controller to set |
|
23 | + * $this->sources. If the request is NOT valid, make sure $this->sources |
|
24 | + * is left an empty array. Then strip any controller-specific options from |
|
25 | + * $options and return it. To serve files, $this->sources must be an array of |
|
26 | + * Minify_Source objects. |
|
27 | + * |
|
28 | + * @param array $options controller and Minify options |
|
29 | + * |
|
30 | + * @return array $options Minify::serve options |
|
31 | + */ |
|
32 | + abstract public function setupSources($options); |
|
33 | 33 | |
34 | - /** |
|
35 | - * Get default Minify options for this controller. |
|
36 | - * |
|
37 | - * Override in subclass to change defaults |
|
38 | - * |
|
39 | - * @return array options for Minify |
|
40 | - */ |
|
41 | - public function getDefaultMinifyOptions() { |
|
42 | - return array( |
|
43 | - 'isPublic' => true |
|
44 | - ,'encodeOutput' => function_exists('gzdeflate') |
|
45 | - ,'encodeMethod' => null // determine later |
|
46 | - ,'encodeLevel' => 9 |
|
47 | - ,'minifierOptions' => array() // no minifier options |
|
48 | - ,'contentTypeCharset' => 'utf-8' |
|
49 | - ,'maxAge' => 1800 // 30 minutes |
|
50 | - ,'rewriteCssUris' => true |
|
51 | - ,'bubbleCssImports' => false |
|
52 | - ,'quiet' => false // serve() will send headers and output |
|
53 | - ,'debug' => false |
|
34 | + /** |
|
35 | + * Get default Minify options for this controller. |
|
36 | + * |
|
37 | + * Override in subclass to change defaults |
|
38 | + * |
|
39 | + * @return array options for Minify |
|
40 | + */ |
|
41 | + public function getDefaultMinifyOptions() { |
|
42 | + return array( |
|
43 | + 'isPublic' => true |
|
44 | + ,'encodeOutput' => function_exists('gzdeflate') |
|
45 | + ,'encodeMethod' => null // determine later |
|
46 | + ,'encodeLevel' => 9 |
|
47 | + ,'minifierOptions' => array() // no minifier options |
|
48 | + ,'contentTypeCharset' => 'utf-8' |
|
49 | + ,'maxAge' => 1800 // 30 minutes |
|
50 | + ,'rewriteCssUris' => true |
|
51 | + ,'bubbleCssImports' => false |
|
52 | + ,'quiet' => false // serve() will send headers and output |
|
53 | + ,'debug' => false |
|
54 | 54 | |
55 | - // if you override these, the response codes MUST be directly after |
|
56 | - // the first space. |
|
57 | - ,'badRequestHeader' => 'HTTP/1.0 400 Bad Request' |
|
58 | - ,'errorHeader' => 'HTTP/1.0 500 Internal Server Error' |
|
55 | + // if you override these, the response codes MUST be directly after |
|
56 | + // the first space. |
|
57 | + ,'badRequestHeader' => 'HTTP/1.0 400 Bad Request' |
|
58 | + ,'errorHeader' => 'HTTP/1.0 500 Internal Server Error' |
|
59 | 59 | |
60 | - // callback function to see/modify content of all sources |
|
61 | - ,'postprocessor' => null |
|
62 | - // file to require to load preprocessor |
|
63 | - ,'postprocessorRequire' => null |
|
64 | - ); |
|
65 | - } |
|
60 | + // callback function to see/modify content of all sources |
|
61 | + ,'postprocessor' => null |
|
62 | + // file to require to load preprocessor |
|
63 | + ,'postprocessorRequire' => null |
|
64 | + ); |
|
65 | + } |
|
66 | 66 | |
67 | - /** |
|
68 | - * Get default minifiers for this controller. |
|
69 | - * |
|
70 | - * Override in subclass to change defaults |
|
71 | - * |
|
72 | - * @return array minifier callbacks for common types |
|
73 | - */ |
|
74 | - public function getDefaultMinifers() { |
|
75 | - $ret[Minify::TYPE_JS] = array('JSMin', 'minify'); |
|
76 | - $ret[Minify::TYPE_CSS] = array('Minify_CSS', 'minify'); |
|
77 | - $ret[Minify::TYPE_HTML] = array('Minify_HTML', 'minify'); |
|
78 | - return $ret; |
|
79 | - } |
|
67 | + /** |
|
68 | + * Get default minifiers for this controller. |
|
69 | + * |
|
70 | + * Override in subclass to change defaults |
|
71 | + * |
|
72 | + * @return array minifier callbacks for common types |
|
73 | + */ |
|
74 | + public function getDefaultMinifers() { |
|
75 | + $ret[Minify::TYPE_JS] = array('JSMin', 'minify'); |
|
76 | + $ret[Minify::TYPE_CSS] = array('Minify_CSS', 'minify'); |
|
77 | + $ret[Minify::TYPE_HTML] = array('Minify_HTML', 'minify'); |
|
78 | + return $ret; |
|
79 | + } |
|
80 | 80 | |
81 | - /** |
|
82 | - * Is a user-given file within an allowable directory, existing, |
|
83 | - * and having an extension js/css/html/txt ? |
|
84 | - * |
|
85 | - * This is a convenience function for controllers that have to accept |
|
86 | - * user-given paths |
|
87 | - * |
|
88 | - * @param string $file full file path (already processed by realpath()) |
|
89 | - * |
|
90 | - * @param array $safeDirs directories where files are safe to serve. Files can also |
|
91 | - * be in subdirectories of these directories. |
|
92 | - * |
|
93 | - * @return bool file is safe |
|
94 | - * |
|
95 | - * @deprecated use checkAllowDirs, checkNotHidden instead |
|
96 | - */ |
|
97 | - public static function _fileIsSafe($file, $safeDirs) |
|
98 | - { |
|
99 | - $pathOk = false; |
|
100 | - foreach ((array)$safeDirs as $safeDir) { |
|
101 | - if (strpos($file, $safeDir) === 0) { |
|
102 | - $pathOk = true; |
|
103 | - break; |
|
104 | - } |
|
105 | - } |
|
106 | - $base = basename($file); |
|
107 | - if (! $pathOk || ! is_file($file) || $base[0] === '.') { |
|
108 | - return false; |
|
109 | - } |
|
110 | - list($revExt) = explode('.', strrev($base)); |
|
111 | - return in_array(strrev($revExt), array('js', 'css', 'html', 'txt')); |
|
112 | - } |
|
81 | + /** |
|
82 | + * Is a user-given file within an allowable directory, existing, |
|
83 | + * and having an extension js/css/html/txt ? |
|
84 | + * |
|
85 | + * This is a convenience function for controllers that have to accept |
|
86 | + * user-given paths |
|
87 | + * |
|
88 | + * @param string $file full file path (already processed by realpath()) |
|
89 | + * |
|
90 | + * @param array $safeDirs directories where files are safe to serve. Files can also |
|
91 | + * be in subdirectories of these directories. |
|
92 | + * |
|
93 | + * @return bool file is safe |
|
94 | + * |
|
95 | + * @deprecated use checkAllowDirs, checkNotHidden instead |
|
96 | + */ |
|
97 | + public static function _fileIsSafe($file, $safeDirs) |
|
98 | + { |
|
99 | + $pathOk = false; |
|
100 | + foreach ((array)$safeDirs as $safeDir) { |
|
101 | + if (strpos($file, $safeDir) === 0) { |
|
102 | + $pathOk = true; |
|
103 | + break; |
|
104 | + } |
|
105 | + } |
|
106 | + $base = basename($file); |
|
107 | + if (! $pathOk || ! is_file($file) || $base[0] === '.') { |
|
108 | + return false; |
|
109 | + } |
|
110 | + list($revExt) = explode('.', strrev($base)); |
|
111 | + return in_array(strrev($revExt), array('js', 'css', 'html', 'txt')); |
|
112 | + } |
|
113 | 113 | |
114 | - /** |
|
115 | - * @param string $file |
|
116 | - * @param array $allowDirs |
|
117 | - * @param string $uri |
|
118 | - * @return bool |
|
119 | - * @throws Exception |
|
120 | - */ |
|
121 | - public static function checkAllowDirs($file, $allowDirs, $uri) |
|
122 | - { |
|
123 | - foreach ((array)$allowDirs as $allowDir) { |
|
124 | - if (strpos($file, $allowDir) === 0) { |
|
125 | - return true; |
|
126 | - } |
|
127 | - } |
|
128 | - throw new Exception("File '$file' is outside \$allowDirs. If the path is" |
|
129 | - . " resolved via an alias/symlink, look into the \$min_symlinks option." |
|
130 | - . " E.g. \$min_symlinks['/" . dirname($uri) . "'] = '" . dirname($file) . "';"); |
|
131 | - } |
|
114 | + /** |
|
115 | + * @param string $file |
|
116 | + * @param array $allowDirs |
|
117 | + * @param string $uri |
|
118 | + * @return bool |
|
119 | + * @throws Exception |
|
120 | + */ |
|
121 | + public static function checkAllowDirs($file, $allowDirs, $uri) |
|
122 | + { |
|
123 | + foreach ((array)$allowDirs as $allowDir) { |
|
124 | + if (strpos($file, $allowDir) === 0) { |
|
125 | + return true; |
|
126 | + } |
|
127 | + } |
|
128 | + throw new Exception("File '$file' is outside \$allowDirs. If the path is" |
|
129 | + . " resolved via an alias/symlink, look into the \$min_symlinks option." |
|
130 | + . " E.g. \$min_symlinks['/" . dirname($uri) . "'] = '" . dirname($file) . "';"); |
|
131 | + } |
|
132 | 132 | |
133 | - /** |
|
134 | - * @param string $file |
|
135 | - * @throws Exception |
|
136 | - */ |
|
137 | - public static function checkNotHidden($file) |
|
138 | - { |
|
139 | - $b = basename($file); |
|
140 | - if (0 === strpos($b, '.')) { |
|
141 | - throw new Exception("Filename '$b' starts with period (may be hidden)"); |
|
142 | - } |
|
143 | - } |
|
133 | + /** |
|
134 | + * @param string $file |
|
135 | + * @throws Exception |
|
136 | + */ |
|
137 | + public static function checkNotHidden($file) |
|
138 | + { |
|
139 | + $b = basename($file); |
|
140 | + if (0 === strpos($b, '.')) { |
|
141 | + throw new Exception("Filename '$b' starts with period (may be hidden)"); |
|
142 | + } |
|
143 | + } |
|
144 | 144 | |
145 | - /** |
|
146 | - * instances of Minify_Source, which provide content and any individual minification needs. |
|
147 | - * |
|
148 | - * @var array |
|
149 | - * |
|
150 | - * @see Minify_Source |
|
151 | - */ |
|
152 | - public $sources = array(); |
|
145 | + /** |
|
146 | + * instances of Minify_Source, which provide content and any individual minification needs. |
|
147 | + * |
|
148 | + * @var array |
|
149 | + * |
|
150 | + * @see Minify_Source |
|
151 | + */ |
|
152 | + public $sources = array(); |
|
153 | 153 | |
154 | - /** |
|
155 | - * Short name to place inside cache id |
|
156 | - * |
|
157 | - * The setupSources() method may choose to set this, making it easier to |
|
158 | - * recognize a particular set of sources/settings in the cache folder. It |
|
159 | - * will be filtered and truncated to make the final cache id <= 250 bytes. |
|
160 | - * |
|
161 | - * @var string |
|
162 | - */ |
|
163 | - public $selectionId = ''; |
|
154 | + /** |
|
155 | + * Short name to place inside cache id |
|
156 | + * |
|
157 | + * The setupSources() method may choose to set this, making it easier to |
|
158 | + * recognize a particular set of sources/settings in the cache folder. It |
|
159 | + * will be filtered and truncated to make the final cache id <= 250 bytes. |
|
160 | + * |
|
161 | + * @var string |
|
162 | + */ |
|
163 | + public $selectionId = ''; |
|
164 | 164 | |
165 | - /** |
|
166 | - * Mix in default controller options with user-given options |
|
167 | - * |
|
168 | - * @param array $options user options |
|
169 | - * |
|
170 | - * @return array mixed options |
|
171 | - */ |
|
172 | - public final function mixInDefaultOptions($options) |
|
173 | - { |
|
174 | - $ret = array_merge( |
|
175 | - $this->getDefaultMinifyOptions(), $options |
|
176 | - ); |
|
177 | - if (! isset($options['minifiers'])) { |
|
178 | - $options['minifiers'] = array(); |
|
179 | - } |
|
180 | - $ret['minifiers'] = array_merge( |
|
181 | - $this->getDefaultMinifers(), $options['minifiers'] |
|
182 | - ); |
|
183 | - return $ret; |
|
184 | - } |
|
165 | + /** |
|
166 | + * Mix in default controller options with user-given options |
|
167 | + * |
|
168 | + * @param array $options user options |
|
169 | + * |
|
170 | + * @return array mixed options |
|
171 | + */ |
|
172 | + public final function mixInDefaultOptions($options) |
|
173 | + { |
|
174 | + $ret = array_merge( |
|
175 | + $this->getDefaultMinifyOptions(), $options |
|
176 | + ); |
|
177 | + if (! isset($options['minifiers'])) { |
|
178 | + $options['minifiers'] = array(); |
|
179 | + } |
|
180 | + $ret['minifiers'] = array_merge( |
|
181 | + $this->getDefaultMinifers(), $options['minifiers'] |
|
182 | + ); |
|
183 | + return $ret; |
|
184 | + } |
|
185 | 185 | |
186 | - /** |
|
187 | - * Analyze sources (if there are any) and set $options 'contentType' |
|
188 | - * and 'lastModifiedTime' if they already aren't. |
|
189 | - * |
|
190 | - * @param array $options options for Minify |
|
191 | - * |
|
192 | - * @return array options for Minify |
|
193 | - */ |
|
194 | - public final function analyzeSources($options = array()) |
|
195 | - { |
|
196 | - if ($this->sources) { |
|
197 | - if (! isset($options['contentType'])) { |
|
198 | - $options['contentType'] = Minify_Source::getContentType($this->sources); |
|
199 | - } |
|
200 | - // last modified is needed for caching, even if setExpires is set |
|
201 | - if (! isset($options['lastModifiedTime'])) { |
|
202 | - $max = 0; |
|
203 | - foreach ($this->sources as $source) { |
|
204 | - $max = max($source->lastModified, $max); |
|
205 | - } |
|
206 | - $options['lastModifiedTime'] = $max; |
|
207 | - } |
|
208 | - } |
|
209 | - return $options; |
|
210 | - } |
|
186 | + /** |
|
187 | + * Analyze sources (if there are any) and set $options 'contentType' |
|
188 | + * and 'lastModifiedTime' if they already aren't. |
|
189 | + * |
|
190 | + * @param array $options options for Minify |
|
191 | + * |
|
192 | + * @return array options for Minify |
|
193 | + */ |
|
194 | + public final function analyzeSources($options = array()) |
|
195 | + { |
|
196 | + if ($this->sources) { |
|
197 | + if (! isset($options['contentType'])) { |
|
198 | + $options['contentType'] = Minify_Source::getContentType($this->sources); |
|
199 | + } |
|
200 | + // last modified is needed for caching, even if setExpires is set |
|
201 | + if (! isset($options['lastModifiedTime'])) { |
|
202 | + $max = 0; |
|
203 | + foreach ($this->sources as $source) { |
|
204 | + $max = max($source->lastModified, $max); |
|
205 | + } |
|
206 | + $options['lastModifiedTime'] = $max; |
|
207 | + } |
|
208 | + } |
|
209 | + return $options; |
|
210 | + } |
|
211 | 211 | |
212 | - /** |
|
213 | - * Send message to the Minify logger |
|
214 | - * |
|
215 | - * @param string $msg |
|
216 | - * |
|
217 | - * @return null |
|
218 | - */ |
|
219 | - public function log($msg) { |
|
220 | - Minify_Logger::log($msg); |
|
221 | - } |
|
212 | + /** |
|
213 | + * Send message to the Minify logger |
|
214 | + * |
|
215 | + * @param string $msg |
|
216 | + * |
|
217 | + * @return null |
|
218 | + */ |
|
219 | + public function log($msg) { |
|
220 | + Minify_Logger::log($msg); |
|
221 | + } |
|
222 | 222 | } |
@@ -12,235 +12,235 @@ |
||
12 | 12 | */ |
13 | 13 | class Minify_Controller_MinApp extends Minify_Controller_Base { |
14 | 14 | |
15 | - /** |
|
16 | - * Set up groups of files as sources |
|
17 | - * |
|
18 | - * @param array $options controller and Minify options |
|
19 | - * |
|
20 | - * @return array Minify options |
|
21 | - */ |
|
22 | - public function setupSources($options) { |
|
23 | - // PHP insecure by default: realpath() and other FS functions can't handle null bytes. |
|
24 | - foreach (array('g', 'b', 'f') as $key) { |
|
25 | - if (isset($_GET[$key])) { |
|
26 | - $_GET[$key] = str_replace("\x00", '', (string)$_GET[$key]); |
|
27 | - } |
|
28 | - } |
|
15 | + /** |
|
16 | + * Set up groups of files as sources |
|
17 | + * |
|
18 | + * @param array $options controller and Minify options |
|
19 | + * |
|
20 | + * @return array Minify options |
|
21 | + */ |
|
22 | + public function setupSources($options) { |
|
23 | + // PHP insecure by default: realpath() and other FS functions can't handle null bytes. |
|
24 | + foreach (array('g', 'b', 'f') as $key) { |
|
25 | + if (isset($_GET[$key])) { |
|
26 | + $_GET[$key] = str_replace("\x00", '', (string)$_GET[$key]); |
|
27 | + } |
|
28 | + } |
|
29 | 29 | |
30 | - // filter controller options |
|
31 | - $cOptions = array_merge( |
|
32 | - array( |
|
33 | - 'allowDirs' => '//' |
|
34 | - ,'groupsOnly' => false |
|
35 | - ,'groups' => array() |
|
36 | - ,'noMinPattern' => '@[-\\.]min\\.(?:js|css)$@i' // matched against basename |
|
37 | - ) |
|
38 | - ,(isset($options['minApp']) ? $options['minApp'] : array()) |
|
39 | - ); |
|
40 | - unset($options['minApp']); |
|
41 | - $sources = array(); |
|
42 | - $this->selectionId = ''; |
|
43 | - $firstMissingResource = null; |
|
44 | - if (isset($_GET['g'])) { |
|
45 | - // add group(s) |
|
46 | - $this->selectionId .= 'g=' . $_GET['g']; |
|
47 | - $keys = explode(',', $_GET['g']); |
|
48 | - if ($keys != array_unique($keys)) { |
|
49 | - $this->log("Duplicate group key found."); |
|
50 | - return $options; |
|
51 | - } |
|
52 | - $keys = explode(',', $_GET['g']); |
|
53 | - foreach ($keys as $key) { |
|
54 | - if (! isset($cOptions['groups'][$key])) { |
|
55 | - $this->log("A group configuration for \"{$key}\" was not found"); |
|
56 | - return $options; |
|
57 | - } |
|
58 | - $files = $cOptions['groups'][$key]; |
|
59 | - // if $files is a single object, casting will break it |
|
60 | - if (is_object($files)) { |
|
61 | - $files = array($files); |
|
62 | - } elseif (! is_array($files)) { |
|
63 | - $files = (array)$files; |
|
64 | - } |
|
65 | - foreach ($files as $file) { |
|
66 | - if ($file instanceof Minify_Source) { |
|
67 | - $sources[] = $file; |
|
68 | - continue; |
|
69 | - } |
|
70 | - if (0 === strpos($file, '//')) { |
|
71 | - $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1); |
|
72 | - } |
|
73 | - $realpath = realpath($file); |
|
74 | - if ($realpath && is_file($realpath)) { |
|
75 | - $sources[] = $this->_getFileSource($realpath, $cOptions); |
|
76 | - } else { |
|
77 | - $this->log("The path \"{$file}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); |
|
78 | - if (null === $firstMissingResource) { |
|
79 | - $firstMissingResource = basename($file); |
|
80 | - continue; |
|
81 | - } else { |
|
82 | - $secondMissingResource = basename($file); |
|
83 | - $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource'"); |
|
84 | - return $options; |
|
85 | - } |
|
86 | - } |
|
87 | - } |
|
88 | - if ($sources) { |
|
89 | - try { |
|
90 | - $this->checkType($sources[0]); |
|
91 | - } catch (Exception $e) { |
|
92 | - $this->log($e->getMessage()); |
|
93 | - return $options; |
|
94 | - } |
|
95 | - } |
|
96 | - } |
|
97 | - } |
|
98 | - if (! $cOptions['groupsOnly'] && isset($_GET['f'])) { |
|
99 | - // try user files |
|
100 | - // The following restrictions are to limit the URLs that minify will |
|
101 | - // respond to. |
|
102 | - if (// verify at least one file, files are single comma separated, |
|
103 | - // and are all same extension |
|
104 | - ! preg_match('/^[^,]+\\.(css|js)(?:,[^,]+\\.\\1)*$/', $_GET['f'], $m) |
|
105 | - // no "//" |
|
106 | - || strpos($_GET['f'], '//') !== false |
|
107 | - // no "\" |
|
108 | - || strpos($_GET['f'], '\\') !== false |
|
109 | - ) { |
|
110 | - $this->log("GET param 'f' was invalid"); |
|
111 | - return $options; |
|
112 | - } |
|
113 | - $ext = ".{$m[1]}"; |
|
114 | - try { |
|
115 | - $this->checkType($m[1]); |
|
116 | - } catch (Exception $e) { |
|
117 | - $this->log($e->getMessage()); |
|
118 | - return $options; |
|
119 | - } |
|
120 | - $files = explode(',', $_GET['f']); |
|
121 | - if ($files != array_unique($files)) { |
|
122 | - $this->log("Duplicate files were specified"); |
|
123 | - return $options; |
|
124 | - } |
|
125 | - if (isset($_GET['b'])) { |
|
126 | - // check for validity |
|
127 | - if (preg_match('@^[^/]+(?:/[^/]+)*$@', $_GET['b']) |
|
128 | - && false === strpos($_GET['b'], '..') |
|
129 | - && $_GET['b'] !== '.') { |
|
130 | - // valid base |
|
131 | - $base = "/{$_GET['b']}/"; |
|
132 | - } else { |
|
133 | - $this->log("GET param 'b' was invalid"); |
|
134 | - return $options; |
|
135 | - } |
|
136 | - } else { |
|
137 | - $base = '/'; |
|
138 | - } |
|
139 | - $allowDirs = array(); |
|
140 | - foreach ((array)$cOptions['allowDirs'] as $allowDir) { |
|
141 | - $allowDirs[] = realpath(str_replace('//', $_SERVER['DOCUMENT_ROOT'] . '/', $allowDir)); |
|
142 | - } |
|
143 | - $base_path = $_SERVER['DOCUMENT_ROOT'].$base; |
|
144 | - // check base against symlinks to support aliases configured via symlinks |
|
145 | - if (!(@file_exists($base_path) && is_dir($base_path) && realpath($base_path) !== false) && |
|
146 | - isset($options['minifierOptions']['text/css']['symlinks'][$t='//'.trim($base, '/')]) && |
|
147 | - ($base_path = realpath($options['minifierOptions']['text/css']['symlinks'][$t]))) { |
|
148 | - $base_path .= '/'; |
|
149 | - $allowDirs[] = $base_path; |
|
150 | - } |
|
151 | - $basenames = array(); // just for cache id |
|
152 | - foreach ($files as $file) { |
|
153 | - $uri = $base . $file; |
|
154 | - $path = $base_path . $file; |
|
155 | - $realpath = realpath($path); |
|
156 | - if (false === $realpath || ! is_file($realpath)) { |
|
157 | - $this->log("The path \"{$path}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); |
|
158 | - if (null === $firstMissingResource) { |
|
159 | - $firstMissingResource = $uri; |
|
160 | - continue; |
|
161 | - } else { |
|
162 | - $secondMissingResource = $uri; |
|
163 | - $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource`'"); |
|
164 | - return $options; |
|
165 | - } |
|
166 | - } |
|
167 | - try { |
|
168 | - parent::checkNotHidden($realpath); |
|
169 | - parent::checkAllowDirs($realpath, $allowDirs, $uri); |
|
170 | - } catch (Exception $e) { |
|
171 | - $this->log($e->getMessage()); |
|
172 | - return $options; |
|
173 | - } |
|
174 | - $sources[] = $this->_getFileSource($realpath, $cOptions); |
|
175 | - $basenames[] = basename($realpath, $ext); |
|
176 | - } |
|
177 | - if ($this->selectionId) { |
|
178 | - $this->selectionId .= '_f='; |
|
179 | - } |
|
180 | - $this->selectionId .= implode(',', $basenames) . $ext; |
|
181 | - } |
|
182 | - if ($sources) { |
|
183 | - if (null !== $firstMissingResource) { |
|
184 | - array_unshift($sources, new Minify_Source(array( |
|
185 | - 'id' => 'missingFile' |
|
186 | - // should not cause cache invalidation |
|
187 | - ,'lastModified' => 0 |
|
188 | - // due to caching, filename is unreliable. |
|
189 | - ,'content' => "/* Minify: at least one missing file. See " . Minify::URL_DEBUG . " */\n" |
|
190 | - ,'minifier' => '' |
|
191 | - ))); |
|
192 | - } |
|
193 | - $this->sources = $sources; |
|
194 | - } else { |
|
195 | - $this->log("No sources to serve"); |
|
196 | - } |
|
197 | - return $options; |
|
198 | - } |
|
30 | + // filter controller options |
|
31 | + $cOptions = array_merge( |
|
32 | + array( |
|
33 | + 'allowDirs' => '//' |
|
34 | + ,'groupsOnly' => false |
|
35 | + ,'groups' => array() |
|
36 | + ,'noMinPattern' => '@[-\\.]min\\.(?:js|css)$@i' // matched against basename |
|
37 | + ) |
|
38 | + ,(isset($options['minApp']) ? $options['minApp'] : array()) |
|
39 | + ); |
|
40 | + unset($options['minApp']); |
|
41 | + $sources = array(); |
|
42 | + $this->selectionId = ''; |
|
43 | + $firstMissingResource = null; |
|
44 | + if (isset($_GET['g'])) { |
|
45 | + // add group(s) |
|
46 | + $this->selectionId .= 'g=' . $_GET['g']; |
|
47 | + $keys = explode(',', $_GET['g']); |
|
48 | + if ($keys != array_unique($keys)) { |
|
49 | + $this->log("Duplicate group key found."); |
|
50 | + return $options; |
|
51 | + } |
|
52 | + $keys = explode(',', $_GET['g']); |
|
53 | + foreach ($keys as $key) { |
|
54 | + if (! isset($cOptions['groups'][$key])) { |
|
55 | + $this->log("A group configuration for \"{$key}\" was not found"); |
|
56 | + return $options; |
|
57 | + } |
|
58 | + $files = $cOptions['groups'][$key]; |
|
59 | + // if $files is a single object, casting will break it |
|
60 | + if (is_object($files)) { |
|
61 | + $files = array($files); |
|
62 | + } elseif (! is_array($files)) { |
|
63 | + $files = (array)$files; |
|
64 | + } |
|
65 | + foreach ($files as $file) { |
|
66 | + if ($file instanceof Minify_Source) { |
|
67 | + $sources[] = $file; |
|
68 | + continue; |
|
69 | + } |
|
70 | + if (0 === strpos($file, '//')) { |
|
71 | + $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1); |
|
72 | + } |
|
73 | + $realpath = realpath($file); |
|
74 | + if ($realpath && is_file($realpath)) { |
|
75 | + $sources[] = $this->_getFileSource($realpath, $cOptions); |
|
76 | + } else { |
|
77 | + $this->log("The path \"{$file}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); |
|
78 | + if (null === $firstMissingResource) { |
|
79 | + $firstMissingResource = basename($file); |
|
80 | + continue; |
|
81 | + } else { |
|
82 | + $secondMissingResource = basename($file); |
|
83 | + $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource'"); |
|
84 | + return $options; |
|
85 | + } |
|
86 | + } |
|
87 | + } |
|
88 | + if ($sources) { |
|
89 | + try { |
|
90 | + $this->checkType($sources[0]); |
|
91 | + } catch (Exception $e) { |
|
92 | + $this->log($e->getMessage()); |
|
93 | + return $options; |
|
94 | + } |
|
95 | + } |
|
96 | + } |
|
97 | + } |
|
98 | + if (! $cOptions['groupsOnly'] && isset($_GET['f'])) { |
|
99 | + // try user files |
|
100 | + // The following restrictions are to limit the URLs that minify will |
|
101 | + // respond to. |
|
102 | + if (// verify at least one file, files are single comma separated, |
|
103 | + // and are all same extension |
|
104 | + ! preg_match('/^[^,]+\\.(css|js)(?:,[^,]+\\.\\1)*$/', $_GET['f'], $m) |
|
105 | + // no "//" |
|
106 | + || strpos($_GET['f'], '//') !== false |
|
107 | + // no "\" |
|
108 | + || strpos($_GET['f'], '\\') !== false |
|
109 | + ) { |
|
110 | + $this->log("GET param 'f' was invalid"); |
|
111 | + return $options; |
|
112 | + } |
|
113 | + $ext = ".{$m[1]}"; |
|
114 | + try { |
|
115 | + $this->checkType($m[1]); |
|
116 | + } catch (Exception $e) { |
|
117 | + $this->log($e->getMessage()); |
|
118 | + return $options; |
|
119 | + } |
|
120 | + $files = explode(',', $_GET['f']); |
|
121 | + if ($files != array_unique($files)) { |
|
122 | + $this->log("Duplicate files were specified"); |
|
123 | + return $options; |
|
124 | + } |
|
125 | + if (isset($_GET['b'])) { |
|
126 | + // check for validity |
|
127 | + if (preg_match('@^[^/]+(?:/[^/]+)*$@', $_GET['b']) |
|
128 | + && false === strpos($_GET['b'], '..') |
|
129 | + && $_GET['b'] !== '.') { |
|
130 | + // valid base |
|
131 | + $base = "/{$_GET['b']}/"; |
|
132 | + } else { |
|
133 | + $this->log("GET param 'b' was invalid"); |
|
134 | + return $options; |
|
135 | + } |
|
136 | + } else { |
|
137 | + $base = '/'; |
|
138 | + } |
|
139 | + $allowDirs = array(); |
|
140 | + foreach ((array)$cOptions['allowDirs'] as $allowDir) { |
|
141 | + $allowDirs[] = realpath(str_replace('//', $_SERVER['DOCUMENT_ROOT'] . '/', $allowDir)); |
|
142 | + } |
|
143 | + $base_path = $_SERVER['DOCUMENT_ROOT'].$base; |
|
144 | + // check base against symlinks to support aliases configured via symlinks |
|
145 | + if (!(@file_exists($base_path) && is_dir($base_path) && realpath($base_path) !== false) && |
|
146 | + isset($options['minifierOptions']['text/css']['symlinks'][$t='//'.trim($base, '/')]) && |
|
147 | + ($base_path = realpath($options['minifierOptions']['text/css']['symlinks'][$t]))) { |
|
148 | + $base_path .= '/'; |
|
149 | + $allowDirs[] = $base_path; |
|
150 | + } |
|
151 | + $basenames = array(); // just for cache id |
|
152 | + foreach ($files as $file) { |
|
153 | + $uri = $base . $file; |
|
154 | + $path = $base_path . $file; |
|
155 | + $realpath = realpath($path); |
|
156 | + if (false === $realpath || ! is_file($realpath)) { |
|
157 | + $this->log("The path \"{$path}\" (realpath \"{$realpath}\") could not be found (or was not a file)"); |
|
158 | + if (null === $firstMissingResource) { |
|
159 | + $firstMissingResource = $uri; |
|
160 | + continue; |
|
161 | + } else { |
|
162 | + $secondMissingResource = $uri; |
|
163 | + $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource`'"); |
|
164 | + return $options; |
|
165 | + } |
|
166 | + } |
|
167 | + try { |
|
168 | + parent::checkNotHidden($realpath); |
|
169 | + parent::checkAllowDirs($realpath, $allowDirs, $uri); |
|
170 | + } catch (Exception $e) { |
|
171 | + $this->log($e->getMessage()); |
|
172 | + return $options; |
|
173 | + } |
|
174 | + $sources[] = $this->_getFileSource($realpath, $cOptions); |
|
175 | + $basenames[] = basename($realpath, $ext); |
|
176 | + } |
|
177 | + if ($this->selectionId) { |
|
178 | + $this->selectionId .= '_f='; |
|
179 | + } |
|
180 | + $this->selectionId .= implode(',', $basenames) . $ext; |
|
181 | + } |
|
182 | + if ($sources) { |
|
183 | + if (null !== $firstMissingResource) { |
|
184 | + array_unshift($sources, new Minify_Source(array( |
|
185 | + 'id' => 'missingFile' |
|
186 | + // should not cause cache invalidation |
|
187 | + ,'lastModified' => 0 |
|
188 | + // due to caching, filename is unreliable. |
|
189 | + ,'content' => "/* Minify: at least one missing file. See " . Minify::URL_DEBUG . " */\n" |
|
190 | + ,'minifier' => '' |
|
191 | + ))); |
|
192 | + } |
|
193 | + $this->sources = $sources; |
|
194 | + } else { |
|
195 | + $this->log("No sources to serve"); |
|
196 | + } |
|
197 | + return $options; |
|
198 | + } |
|
199 | 199 | |
200 | - /** |
|
201 | - * @param string $file |
|
202 | - * |
|
203 | - * @param array $cOptions |
|
204 | - * |
|
205 | - * @return Minify_Source |
|
206 | - */ |
|
207 | - protected function _getFileSource($file, $cOptions) |
|
208 | - { |
|
209 | - $spec['filepath'] = $file; |
|
210 | - if ($cOptions['noMinPattern'] && preg_match($cOptions['noMinPattern'], basename($file))) { |
|
211 | - if (preg_match('~\.css$~i', $file)) { |
|
212 | - $spec['minifyOptions']['compress'] = false; |
|
213 | - } else { |
|
214 | - $spec['minifier'] = ''; |
|
215 | - } |
|
216 | - } |
|
217 | - return new Minify_Source($spec); |
|
218 | - } |
|
200 | + /** |
|
201 | + * @param string $file |
|
202 | + * |
|
203 | + * @param array $cOptions |
|
204 | + * |
|
205 | + * @return Minify_Source |
|
206 | + */ |
|
207 | + protected function _getFileSource($file, $cOptions) |
|
208 | + { |
|
209 | + $spec['filepath'] = $file; |
|
210 | + if ($cOptions['noMinPattern'] && preg_match($cOptions['noMinPattern'], basename($file))) { |
|
211 | + if (preg_match('~\.css$~i', $file)) { |
|
212 | + $spec['minifyOptions']['compress'] = false; |
|
213 | + } else { |
|
214 | + $spec['minifier'] = ''; |
|
215 | + } |
|
216 | + } |
|
217 | + return new Minify_Source($spec); |
|
218 | + } |
|
219 | 219 | |
220 | - protected $_type = null; |
|
220 | + protected $_type = null; |
|
221 | 221 | |
222 | - /** |
|
223 | - * Make sure that only source files of a single type are registered |
|
224 | - * |
|
225 | - * @param string $sourceOrExt |
|
226 | - * |
|
227 | - * @throws Exception |
|
228 | - */ |
|
229 | - public function checkType($sourceOrExt) |
|
230 | - { |
|
231 | - if ($sourceOrExt === 'js') { |
|
232 | - $type = Minify::TYPE_JS; |
|
233 | - } elseif ($sourceOrExt === 'css') { |
|
234 | - $type = Minify::TYPE_CSS; |
|
235 | - } elseif ($sourceOrExt->contentType !== null) { |
|
236 | - $type = $sourceOrExt->contentType; |
|
237 | - } else { |
|
238 | - return; |
|
239 | - } |
|
240 | - if ($this->_type === null) { |
|
241 | - $this->_type = $type; |
|
242 | - } elseif ($this->_type !== $type) { |
|
243 | - throw new Exception('Content-Type mismatch'); |
|
244 | - } |
|
245 | - } |
|
222 | + /** |
|
223 | + * Make sure that only source files of a single type are registered |
|
224 | + * |
|
225 | + * @param string $sourceOrExt |
|
226 | + * |
|
227 | + * @throws Exception |
|
228 | + */ |
|
229 | + public function checkType($sourceOrExt) |
|
230 | + { |
|
231 | + if ($sourceOrExt === 'js') { |
|
232 | + $type = Minify::TYPE_JS; |
|
233 | + } elseif ($sourceOrExt === 'css') { |
|
234 | + $type = Minify::TYPE_CSS; |
|
235 | + } elseif ($sourceOrExt->contentType !== null) { |
|
236 | + $type = $sourceOrExt->contentType; |
|
237 | + } else { |
|
238 | + return; |
|
239 | + } |
|
240 | + if ($this->_type === null) { |
|
241 | + $this->_type = $type; |
|
242 | + } elseif ($this->_type !== $type) { |
|
243 | + throw new Exception('Content-Type mismatch'); |
|
244 | + } |
|
245 | + } |
|
246 | 246 | } |
@@ -26,51 +26,51 @@ |
||
26 | 26 | */ |
27 | 27 | class Minify_Controller_Files extends Minify_Controller_Base { |
28 | 28 | |
29 | - /** |
|
30 | - * Set up file sources |
|
31 | - * |
|
32 | - * @param array $options controller and Minify options |
|
33 | - * @return array Minify options |
|
34 | - * |
|
35 | - * Controller options: |
|
36 | - * |
|
37 | - * 'files': (required) array of complete file paths, or a single path |
|
38 | - */ |
|
39 | - public function setupSources($options) { |
|
40 | - // strip controller options |
|
29 | + /** |
|
30 | + * Set up file sources |
|
31 | + * |
|
32 | + * @param array $options controller and Minify options |
|
33 | + * @return array Minify options |
|
34 | + * |
|
35 | + * Controller options: |
|
36 | + * |
|
37 | + * 'files': (required) array of complete file paths, or a single path |
|
38 | + */ |
|
39 | + public function setupSources($options) { |
|
40 | + // strip controller options |
|
41 | 41 | |
42 | - $files = $options['files']; |
|
43 | - // if $files is a single object, casting will break it |
|
44 | - if (is_object($files)) { |
|
45 | - $files = array($files); |
|
46 | - } elseif (! is_array($files)) { |
|
47 | - $files = (array)$files; |
|
48 | - } |
|
49 | - unset($options['files']); |
|
42 | + $files = $options['files']; |
|
43 | + // if $files is a single object, casting will break it |
|
44 | + if (is_object($files)) { |
|
45 | + $files = array($files); |
|
46 | + } elseif (! is_array($files)) { |
|
47 | + $files = (array)$files; |
|
48 | + } |
|
49 | + unset($options['files']); |
|
50 | 50 | |
51 | - $sources = array(); |
|
52 | - foreach ($files as $file) { |
|
53 | - if ($file instanceof Minify_Source) { |
|
54 | - $sources[] = $file; |
|
55 | - continue; |
|
56 | - } |
|
57 | - if (0 === strpos($file, '//')) { |
|
58 | - $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1); |
|
59 | - } |
|
60 | - $realPath = realpath($file); |
|
61 | - if (is_file($realPath)) { |
|
62 | - $sources[] = new Minify_Source(array( |
|
63 | - 'filepath' => $realPath |
|
64 | - )); |
|
65 | - } else { |
|
66 | - $this->log("The path \"{$file}\" could not be found (or was not a file)"); |
|
67 | - return $options; |
|
68 | - } |
|
69 | - } |
|
70 | - if ($sources) { |
|
71 | - $this->sources = $sources; |
|
72 | - } |
|
73 | - return $options; |
|
74 | - } |
|
51 | + $sources = array(); |
|
52 | + foreach ($files as $file) { |
|
53 | + if ($file instanceof Minify_Source) { |
|
54 | + $sources[] = $file; |
|
55 | + continue; |
|
56 | + } |
|
57 | + if (0 === strpos($file, '//')) { |
|
58 | + $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1); |
|
59 | + } |
|
60 | + $realPath = realpath($file); |
|
61 | + if (is_file($realPath)) { |
|
62 | + $sources[] = new Minify_Source(array( |
|
63 | + 'filepath' => $realPath |
|
64 | + )); |
|
65 | + } else { |
|
66 | + $this->log("The path \"{$file}\" could not be found (or was not a file)"); |
|
67 | + return $options; |
|
68 | + } |
|
69 | + } |
|
70 | + if ($sources) { |
|
71 | + $this->sources = $sources; |
|
72 | + } |
|
73 | + return $options; |
|
74 | + } |
|
75 | 75 | } |
76 | 76 |