diff options
author | Nicolas Lœuillet <nicolas@loeuillet.org> | 2014-07-25 07:27:21 +0200 |
---|---|---|
committer | Nicolas Lœuillet <nicolas@loeuillet.org> | 2014-07-25 07:27:21 +0200 |
commit | fa9a7bbb3c61116e5db76c9f25ef2340fef971d7 (patch) | |
tree | cd733e8548290158d578da185bd541e7fe4b1a31 /inc/poche/Tools.class.php | |
parent | ebd6bf6007e0fad4c3e11dac0e79f687e1d195a2 (diff) | |
parent | 830612f555d8bc72669fe9bc0686680001af0e52 (diff) | |
download | wallabag-fa9a7bbb3c61116e5db76c9f25ef2340fef971d7.tar.gz wallabag-fa9a7bbb3c61116e5db76c9f25ef2340fef971d7.tar.zst wallabag-fa9a7bbb3c61116e5db76c9f25ef2340fef971d7.zip |
Merge branch 'fix/securityAllowedActions' into dev
Diffstat (limited to 'inc/poche/Tools.class.php')
-rwxr-xr-x | inc/poche/Tools.class.php | 187 |
1 files changed, 143 insertions, 44 deletions
diff --git a/inc/poche/Tools.class.php b/inc/poche/Tools.class.php index cc01f403..63137d76 100755 --- a/inc/poche/Tools.class.php +++ b/inc/poche/Tools.class.php | |||
@@ -5,19 +5,18 @@ | |||
5 | * @category wallabag | 5 | * @category wallabag |
6 | * @author Nicolas Lœuillet <nicolas@loeuillet.org> | 6 | * @author Nicolas Lœuillet <nicolas@loeuillet.org> |
7 | * @copyright 2013 | 7 | * @copyright 2013 |
8 | * @license http://www.wtfpl.net/ see COPYING file | 8 | * @license http://opensource.org/licenses/MIT see COPYING file |
9 | */ | 9 | */ |
10 | 10 | ||
11 | class Tools | 11 | final class Tools |
12 | { | 12 | { |
13 | /** | ||
14 | * Initialize PHP environment | ||
15 | */ | ||
13 | public static function initPhp() | 16 | public static function initPhp() |
14 | { | 17 | { |
15 | define('START_TIME', microtime(true)); | 18 | define('START_TIME', microtime(true)); |
16 | 19 | ||
17 | if (phpversion() < 5) { | ||
18 | die(_('Oops, it seems you don\'t have PHP 5.')); | ||
19 | } | ||
20 | |||
21 | function stripslashesDeep($value) { | 20 | function stripslashesDeep($value) { |
22 | return is_array($value) | 21 | return is_array($value) |
23 | ? array_map('stripslashesDeep', $value) | 22 | ? array_map('stripslashesDeep', $value) |
@@ -34,6 +33,11 @@ class Tools | |||
34 | register_shutdown_function('ob_end_flush'); | 33 | register_shutdown_function('ob_end_flush'); |
35 | } | 34 | } |
36 | 35 | ||
36 | /** | ||
37 | * Get wallabag instance URL | ||
38 | * | ||
39 | * @return string | ||
40 | */ | ||
37 | public static function getPocheUrl() | 41 | public static function getPocheUrl() |
38 | { | 42 | { |
39 | $https = (!empty($_SERVER['HTTPS']) | 43 | $https = (!empty($_SERVER['HTTPS']) |
@@ -67,6 +71,11 @@ class Tools | |||
67 | . $host . $serverport . $scriptname; | 71 | . $host . $serverport . $scriptname; |
68 | } | 72 | } |
69 | 73 | ||
74 | /** | ||
75 | * Redirects to a URL | ||
76 | * | ||
77 | * @param string $url | ||
78 | */ | ||
70 | public static function redirect($url = '') | 79 | public static function redirect($url = '') |
71 | { | 80 | { |
72 | if ($url === '') { | 81 | if ($url === '') { |
@@ -87,11 +96,18 @@ class Tools | |||
87 | $url = $ref; | 96 | $url = $ref; |
88 | } | 97 | } |
89 | } | 98 | } |
99 | |||
90 | self::logm('redirect to ' . $url); | 100 | self::logm('redirect to ' . $url); |
91 | header('Location: '.$url); | 101 | header('Location: '.$url); |
92 | exit(); | 102 | exit(); |
93 | } | 103 | } |
94 | 104 | ||
105 | /** | ||
106 | * Returns name of the template file to display | ||
107 | * | ||
108 | * @param $view | ||
109 | * @return string | ||
110 | */ | ||
95 | public static function getTplFile($view) | 111 | public static function getTplFile($view) |
96 | { | 112 | { |
97 | $views = array( | 113 | $views = array( |
@@ -99,13 +115,15 @@ class Tools | |||
99 | 'edit-tags', 'view', 'login', 'error' | 115 | 'edit-tags', 'view', 'login', 'error' |
100 | ); | 116 | ); |
101 | 117 | ||
102 | if (in_array($view, $views)) { | 118 | return (in_array($view, $views) ? $view . '.twig' : 'home.twig'); |
103 | return $view . '.twig'; | ||
104 | } | ||
105 | |||
106 | return 'home.twig'; | ||
107 | } | 119 | } |
108 | 120 | ||
121 | /** | ||
122 | * Download a file (typically, for downloading pictures on web server) | ||
123 | * | ||
124 | * @param $url | ||
125 | * @return bool|mixed|string | ||
126 | */ | ||
109 | public static function getFile($url) | 127 | public static function getFile($url) |
110 | { | 128 | { |
111 | $timeout = 15; | 129 | $timeout = 15; |
@@ -186,6 +204,11 @@ class Tools | |||
186 | } | 204 | } |
187 | } | 205 | } |
188 | 206 | ||
207 | /** | ||
208 | * Headers for JSON export | ||
209 | * | ||
210 | * @param $data | ||
211 | */ | ||
189 | public static function renderJson($data) | 212 | public static function renderJson($data) |
190 | { | 213 | { |
191 | header('Cache-Control: no-cache, must-revalidate'); | 214 | header('Cache-Control: no-cache, must-revalidate'); |
@@ -195,6 +218,11 @@ class Tools | |||
195 | exit(); | 218 | exit(); |
196 | } | 219 | } |
197 | 220 | ||
221 | /** | ||
222 | * Create new line in log file | ||
223 | * | ||
224 | * @param $message | ||
225 | */ | ||
198 | public static function logm($message) | 226 | public static function logm($message) |
199 | { | 227 | { |
200 | if (DEBUG_POCHE && php_sapi_name() != 'cli') { | 228 | if (DEBUG_POCHE && php_sapi_name() != 'cli') { |
@@ -204,36 +232,57 @@ class Tools | |||
204 | } | 232 | } |
205 | } | 233 | } |
206 | 234 | ||
235 | /** | ||
236 | * Encode a URL by using a salt | ||
237 | * | ||
238 | * @param $string | ||
239 | * @return string | ||
240 | */ | ||
207 | public static function encodeString($string) | 241 | public static function encodeString($string) |
208 | { | 242 | { |
209 | return sha1($string . SALT); | 243 | return sha1($string . SALT); |
210 | } | 244 | } |
211 | 245 | ||
246 | /** | ||
247 | * Cleans a variable | ||
248 | * | ||
249 | * @param $var | ||
250 | * @param string $default | ||
251 | * @return string | ||
252 | */ | ||
212 | public static function checkVar($var, $default = '') | 253 | public static function checkVar($var, $default = '') |
213 | { | 254 | { |
214 | return ((isset ($_REQUEST["$var"])) ? htmlentities($_REQUEST["$var"]) : $default); | 255 | return ((isset($_REQUEST["$var"])) ? htmlentities($_REQUEST["$var"]) : $default); |
215 | } | 256 | } |
216 | 257 | ||
258 | /** | ||
259 | * Returns the domain name for a URL | ||
260 | * | ||
261 | * @param $url | ||
262 | * @return string | ||
263 | */ | ||
217 | public static function getDomain($url) | 264 | public static function getDomain($url) |
218 | { | 265 | { |
219 | return parse_url($url, PHP_URL_HOST); | 266 | return parse_url($url, PHP_URL_HOST); |
220 | } | 267 | } |
221 | 268 | ||
222 | public static function getReadingTime($text) { | 269 | /** |
223 | $word = str_word_count(strip_tags($text)); | 270 | * For a given text, we calculate reading time for an article |
224 | $minutes = floor($word / 200); | 271 | * |
225 | $seconds = floor($word % 200 / (200 / 60)); | 272 | * @param $text |
226 | $time = array('minutes' => $minutes, 'seconds' => $seconds); | 273 | * @return float |
227 | 274 | */ | |
228 | return $minutes; | 275 | public static function getReadingTime($text) |
229 | } | 276 | { |
230 | 277 | return floor(str_word_count(strip_tags($text)) / 200); | |
231 | public static function getDocLanguage($userlanguage) { | ||
232 | $lang = explode('.', $userlanguage); | ||
233 | return str_replace('_', '-', $lang[0]); | ||
234 | } | 278 | } |
235 | 279 | ||
236 | public static function status($status_code) | 280 | /** |
281 | * Returns the correct header for a status code | ||
282 | * | ||
283 | * @param $status_code | ||
284 | */ | ||
285 | private static function _status($status_code) | ||
237 | { | 286 | { |
238 | if (strpos(php_sapi_name(), 'apache') !== false) { | 287 | if (strpos(php_sapi_name(), 'apache') !== false) { |
239 | 288 | ||
@@ -245,9 +294,13 @@ class Tools | |||
245 | } | 294 | } |
246 | } | 295 | } |
247 | 296 | ||
248 | public static function download_db() { | 297 | /** |
298 | * Download the sqlite database | ||
299 | */ | ||
300 | public static function downloadDb() | ||
301 | { | ||
249 | header('Content-Disposition: attachment; filename="poche.sqlite.gz"'); | 302 | header('Content-Disposition: attachment; filename="poche.sqlite.gz"'); |
250 | self::status(200); | 303 | self::_status(200); |
251 | 304 | ||
252 | header('Content-Transfer-Encoding: binary'); | 305 | header('Content-Transfer-Encoding: binary'); |
253 | header('Content-Type: application/octet-stream'); | 306 | header('Content-Type: application/octet-stream'); |
@@ -256,18 +309,24 @@ class Tools | |||
256 | exit; | 309 | exit; |
257 | } | 310 | } |
258 | 311 | ||
312 | /** | ||
313 | * Get the content for a given URL (by a call to FullTextFeed) | ||
314 | * | ||
315 | * @param Url $url | ||
316 | * @return mixed | ||
317 | */ | ||
259 | public static function getPageContent(Url $url) | 318 | public static function getPageContent(Url $url) |
260 | { | 319 | { |
261 | // Saving and clearing context | 320 | // Saving and clearing context |
262 | $REAL = array(); | 321 | $REAL = array(); |
263 | foreach( $GLOBALS as $key => $value ) { | 322 | foreach( $GLOBALS as $key => $value ) { |
264 | if( $key != 'GLOBALS' && $key != '_SESSION' && $key != 'HTTP_SESSION_VARS' ) { | 323 | if( $key != 'GLOBALS' && $key != '_SESSION' && $key != 'HTTP_SESSION_VARS' ) { |
265 | $GLOBALS[$key] = array(); | 324 | $GLOBALS[$key] = array(); |
266 | $REAL[$key] = $value; | 325 | $REAL[$key] = $value; |
267 | } | 326 | } |
268 | } | 327 | } |
269 | // Saving and clearing session | 328 | // Saving and clearing session |
270 | if ( isset($_SESSION) ) { | 329 | if (isset($_SESSION)) { |
271 | $REAL_SESSION = array(); | 330 | $REAL_SESSION = array(); |
272 | foreach( $_SESSION as $key => $value ) { | 331 | foreach( $_SESSION as $key => $value ) { |
273 | $REAL_SESSION[$key] = $value; | 332 | $REAL_SESSION[$key] = $value; |
@@ -279,12 +338,12 @@ class Tools | |||
279 | $scope = function() { | 338 | $scope = function() { |
280 | extract( func_get_arg(1) ); | 339 | extract( func_get_arg(1) ); |
281 | $_GET = $_REQUEST = array( | 340 | $_GET = $_REQUEST = array( |
282 | "url" => $url->getUrl(), | 341 | "url" => $url->getUrl(), |
283 | "max" => 5, | 342 | "max" => 5, |
284 | "links" => "preserve", | 343 | "links" => "preserve", |
285 | "exc" => "", | 344 | "exc" => "", |
286 | "format" => "json", | 345 | "format" => "json", |
287 | "submit" => "Create Feed" | 346 | "submit" => "Create Feed" |
288 | ); | 347 | ); |
289 | ob_start(); | 348 | ob_start(); |
290 | require func_get_arg(0); | 349 | require func_get_arg(0); |
@@ -292,23 +351,26 @@ class Tools | |||
292 | ob_end_clean(); | 351 | ob_end_clean(); |
293 | return $json; | 352 | return $json; |
294 | }; | 353 | }; |
295 | $json = $scope( "inc/3rdparty/makefulltextfeed.php", array("url" => $url) ); | 354 | |
355 | $json = $scope("inc/3rdparty/makefulltextfeed.php", array("url" => $url)); | ||
296 | 356 | ||
297 | // Clearing and restoring context | 357 | // Clearing and restoring context |
298 | foreach( $GLOBALS as $key => $value ) { | 358 | foreach ($GLOBALS as $key => $value) { |
299 | if( $key != "GLOBALS" && $key != "_SESSION" ) { | 359 | if($key != "GLOBALS" && $key != "_SESSION" ) { |
300 | unset($GLOBALS[$key]); | 360 | unset($GLOBALS[$key]); |
301 | } | 361 | } |
302 | } | 362 | } |
303 | foreach( $REAL as $key => $value ) { | 363 | foreach ($REAL as $key => $value) { |
304 | $GLOBALS[$key] = $value; | 364 | $GLOBALS[$key] = $value; |
305 | } | 365 | } |
366 | |||
306 | // Clearing and restoring session | 367 | // Clearing and restoring session |
307 | if ( isset($REAL_SESSION) ) { | 368 | if (isset($REAL_SESSION)) { |
308 | foreach( $_SESSION as $key => $value ) { | 369 | foreach($_SESSION as $key => $value) { |
309 | unset($_SESSION[$key]); | 370 | unset($_SESSION[$key]); |
310 | } | 371 | } |
311 | foreach( $REAL_SESSION as $key => $value ) { | 372 | |
373 | foreach($REAL_SESSION as $key => $value) { | ||
312 | $_SESSION[$key] = $value; | 374 | $_SESSION[$key] = $value; |
313 | } | 375 | } |
314 | } | 376 | } |
@@ -318,11 +380,48 @@ class Tools | |||
318 | 380 | ||
319 | /** | 381 | /** |
320 | * Returns whether we handle an AJAX (XMLHttpRequest) request. | 382 | * Returns whether we handle an AJAX (XMLHttpRequest) request. |
383 | * | ||
321 | * @return boolean whether we handle an AJAX (XMLHttpRequest) request. | 384 | * @return boolean whether we handle an AJAX (XMLHttpRequest) request. |
322 | */ | 385 | */ |
323 | public static function isAjaxRequest() | 386 | public static function isAjaxRequest() |
324 | { | 387 | { |
325 | return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest'; | 388 | return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest'; |
389 | } | ||
390 | |||
391 | /* | ||
392 | * Empty cache folder | ||
393 | */ | ||
394 | public static function emptyCache() | ||
395 | { | ||
396 | $files = new RecursiveIteratorIterator( | ||
397 | new RecursiveDirectoryIterator(CACHE, RecursiveDirectoryIterator::SKIP_DOTS), | ||
398 | RecursiveIteratorIterator::CHILD_FIRST | ||
399 | ); | ||
400 | |||
401 | foreach ($files as $fileInfo) { | ||
402 | $todo = ($fileInfo->isDir() ? 'rmdir' : 'unlink'); | ||
403 | $todo($fileInfo->getRealPath()); | ||
404 | } | ||
405 | |||
406 | Tools::logm('empty cache'); | ||
407 | Tools::redirect(); | ||
408 | } | ||
409 | |||
410 | public static function generateToken() | ||
411 | { | ||
412 | if (ini_get('open_basedir') === '') { | ||
413 | if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { | ||
414 | // alternative to /dev/urandom for Windows | ||
415 | $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20); | ||
416 | } else { | ||
417 | $token = substr(base64_encode(file_get_contents('/dev/urandom', false, null, 0, 20)), 0, 15); | ||
418 | } | ||
419 | } | ||
420 | else { | ||
421 | $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20); | ||
422 | } | ||
423 | |||
424 | return str_replace('+', '', $token); | ||
326 | } | 425 | } |
327 | 426 | ||
328 | } | 427 | } |