xref: /template/mikio/css.php (revision 703d73e0256405f80edfab9393b332ee7c436a97)
1<?php
2/**
3 * Mikio CSS/LESS Engine
4 *
5 * @link    http://dokuwiki.org/template:mikio
6 * @author  James Collins <james.collins@outlook.com.au>
7 * @license GPLv2 (http://www.gnu.org/licenses/gpl-2.0.html)
8 */
9
10if(!function_exists('getallheaders')) {
11	function getallheaders() {
12		$headers = [];
13		foreach($_SERVER as $name => $value) {
14			if(substr($name, 0, 5) == 'HTTP_') {
15				$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
16			}
17		}
18		return $headers;
19	}
20}
21
22if(!function_exists('ctype_alnum')) {
23    function ctype_alnum($var) {
24        return preg_match('/^[a-zA-Z0-9]+$/', $var);
25    }
26}
27
28if(!function_exists('ctype_alpha')) {
29    function ctype_alpha($var) {
30        return preg_match('/^[a-zA-Z]+$/', $var);
31    }
32}
33
34if(!function_exists('ctype_cntrl')) {
35    function ctype_cntrl($var) {
36        return preg_match('/^[\x00-\x1F\x7F]+$/', $var);
37    }
38}
39
40if(!function_exists('ctype_digit')) {
41    function ctype_digit($var) {
42        return preg_match('/^[0-9]+$/', $var);
43    }
44}
45
46if(!function_exists('ctype_graph')) {
47    function ctype_graph($var) {
48        return preg_match('/^[\x20-\x7E\x80-\xFF]+$/', $var);
49    }
50}
51
52if(!function_exists('ctype_lower')) {
53    function ctype_lower($var) {
54        return preg_match('/^[a-z]+$/', $var);
55    }
56}
57
58if(!function_exists('ctype_print')) {
59    function ctype_print($var) {
60        return preg_match('/^[\x20-\x7E\x80-\xFF]+$/', $var);
61    }
62}
63
64if(!function_exists('ctype_punct')) {
65    function ctype_punct($var) {
66        return preg_match('/^[^\w\s]+$/', $var);
67    }
68}
69
70if(!function_exists('ctype_space')) {
71    function ctype_space($var) {
72        return preg_match('/^[\r\t\n]+$/', $var);
73    }
74}
75
76if(!function_exists('ctype_upper')) {
77    function ctype_upper($var) {
78        return preg_match('/^[A-Z]+$/', $var);
79    }
80}
81
82if(!function_exists('ctype_xdigit')) {
83    function ctype_upper($var) {
84        return preg_match('/^[0-9A-Fa-f]+$/', $var);
85    }
86}
87
88try {
89    if(!function_exists('ctype_digit')) {
90        if(isset($_GET['css'])) {
91            $baseDir = dirname(__FILE__) . '/';
92            $cssFile = realpath($baseDir . $_GET['css']);
93            if(strtolower(substr($cssFile, -5)) == '.less') {
94                $cssFile = substr($cssFile, 0, -5) . '.css';
95                if(file_exists($cssFile)) {
96                    echo file_get_contents($cssFile);
97                    exit;
98                }
99            }
100        }
101
102        throw new Exception('ctype extension not installed');
103    }
104
105    $lesscLib = '../../../vendor/marcusschwarz/lesserphp/lessc.inc.php';
106    if(!file_exists($lesscLib))
107        $lesscLib = '../../../../../app/dokuwiki/vendor/marcusschwarz/lesserphp/lessc.inc.php';
108
109    if(file_exists($lesscLib)) {
110        @require_once($lesscLib);
111
112        if(isset($_GET['css'])) {
113            $baseDir = dirname(__FILE__) . '/';
114            $cssFile = realpath($baseDir . $_GET['css']);
115
116            if(strpos($cssFile, $baseDir) === 0 && file_exists($cssFile)) {
117                $lastModified = filemtime($cssFile);
118                $eTagFile = md5_file($cssFile);
119                $eTagHeader = (isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE);
120
121                header('Content-Type: text/css; charset=utf-8');
122                header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
123                header('Etag: ' . $eTagFile);
124                header('Cache-Control: public, max-age=604800, immutable');
125
126                if(@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified || $eTagHeader == $eTagFile) {
127                    header('HTTP/1.1 304 Not Modified');
128                    exit;
129                }
130
131                $css = file_get_contents($cssFile);
132
133                $less = new lessc();
134                $less->setPreserveComments(false);
135
136                $rawVars = Array();
137                if(file_exists('style.ini')) $rawVars = array_merge($rawVars, parse_ini_file('style.ini', TRUE));
138                if(file_exists('../../../conf/tpl/mikio/style.ini')) $rawVars = array_merge($rawVars, parse_ini_file('../../../conf/tpl/mikio/style.ini', TRUE));
139
140                $vars = Array();
141                if(isset($rawVars['replacements'])) {
142                    foreach($rawVars['replacements'] as $key=>$val) {
143                        if(substr($key, 0, 2) == '__' && substr($key, -2) == '__') {
144                            $vars['ini_' . substr($key, 2, -2)] = $val;
145                        }
146                    }
147                }
148
149                if(count($vars) > 0) {
150                    $less->setVariables($vars);
151                }
152
153                $css = $less->compile($css);
154
155				$accept_encoding = @getallheaders()['Accept-Encoding'];
156     	        if($accept_encoding && preg_match('/ *gzip *,?/', $accept_encoding)) {
157               	    header('Content-Encoding: gzip');
158                		echo gzencode($css);
159            	} else {
160                		echo $css;
161                }
162            } else {
163                header('HTTP/1.1 404 Not Found');
164                echo "The requested file could not be found";
165            }
166        } else {
167            header('HTTP/1.1 404 Not Found');
168            echo "The requested file could not be found";
169        }
170    } else {
171        throw new Exception('Lessc library not found');
172    }
173}
174catch(Exception $e) {
175    header('HTTP/1.1 500 Internal Server Error');
176    echo $e;
177}
178