]> git.mxchange.org Git - ctracker.git/blob - libs/lib_general.php
Continued:
[ctracker.git] / libs / lib_general.php
1 <?php
2 /**
3  * General functions library
4  *
5  * @author              Roland Haeder <webmaster@shipsimu.org>
6  * @version             3.0.0
7  * @copyright   Copyright (c) 2009 - 2017 Cracker Tracker Team
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.shipsimu.org
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <http://www.gnu.org/licenses/>.
23  */
24
25 // Implode recursive a multi-dimension array, taken from www.php.net
26 function implode_r (string $glue, array $array, string $array_name = NULL) {
27         $return = [];
28         while (list($key,$value) = @each($array)) {
29                 if (is_array($value)) {
30                         // Is an array again, so call recursive
31                         $return[] = implode_r($glue, $value, (string) $key);
32                 } else {
33                         if ($array_name != NULL) {
34                                 $return[] = $array_name . '[' . (string) $key . ']=' . $value . "\n";
35                         } else {
36                                 $return[] = $key . '=' . $value."\n";
37                         }
38                 }
39         }
40
41         // Return resulting array
42         return implode($glue, $return);
43 }
44
45 // Implode a simple array with a 'call-back' to our escaper function
46 function implode_secure (array $array) {
47         // Return string
48         $return = '';
49
50         // Implode all data
51         foreach ($array as $entry) {
52                 // Don't escape some
53                 if (in_array($entry, array('NOW()'))) {
54                         // Add it with non-string glue
55                         $return .= $entry . ',';
56                 } elseif (empty($entry)) {
57                         // Empty strings need no escaping
58                         $return .= '"",';
59                 } else {
60                         // Secure this string and add it
61                         $return .= '"' . crackerTrackerEscapeString($entry) . '",';
62                 }
63         }
64
65         // Remove last char
66         $return = substr($return, 0, -1);
67
68         // Return this string
69         return $return;
70 }
71
72 // Load configuration, if found
73 function crackerTrackerLoadConfiguration () {
74         // FQFN
75         $fqfn = sprintf('%s/config/db_config.php', $GLOBALS['ctracker_base_path']);
76
77         // Is the file readable?
78         if (!isCrackerTrackerFileFound($fqfn)) {
79                 // No config file found
80                 die(__FUNCTION__.': No configuration file found.');
81         }
82
83         // Load it
84         require $fqfn;
85
86         // Load email header
87         $GLOBALS['ctracker_header'] = crackerTrackerLoadEmailTemplate('header');
88 }
89
90 // Getter for ctracker_debug_enabled
91 function isCrackerTrackerDebug () {
92         // Is it set?
93         $result = ((isset($GLOBALS['ctracker_debug_enabled'])) && ($GLOBALS['ctracker_debug_enabled'] === true));
94
95         // Debug message
96         //* DEBUG: */ error_log('result=' . intval($result));
97
98         // Return it
99         return $result;
100 }
101
102 // Determines the real remote address
103 function determineCrackerTrackerRealRemoteAddress () {
104         // Initial value
105         $address = '0.0.0.0';
106
107         // Is a proxy in use?
108         if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
109                 // Proxy was used
110                 $address = trim($_SERVER['HTTP_X_FORWARDED_FOR']);
111         } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
112                 // Yet, another proxy
113                 $address = trim($_SERVER['HTTP_CLIENT_IP']);
114         } elseif (isset($_SERVER['REMOTE_ADDR'])) {
115                 // The regular address when no proxy was used
116                 $address = trim(getenv('REMOTE_ADDR'));
117         }
118
119         if ($address == 'unknown') {
120                 // Invalid IP somehow given
121                 $address = '0.0.0.0';
122         } elseif (strstr($address, ',')) {
123                 // This strips out the real address from proxy output
124                 $addressArray = explode(',', $address);
125                 $address = $addressArray[0];
126         }
127
128         // Return the result
129         return $address;
130 }
131
132 // Determine if a proxy was used
133 function isCrackerTrackerProxyUsed () {
134         // Check if specific entries are set
135         $proxyUsed = ((isset($_SERVER['HTTP_X_FORWARDED_FOR'])) || (isset($_SERVER['HTTP_CLIENT_IP'])));
136
137         // Return result
138         return $proxyUsed;
139 }
140
141 // Detects the user-agent string
142 function crackerTrackerUserAgent (bool $sanitize = false) {
143         // Default is 'unknown'
144         $ua = 'unknown';
145
146         // Is the entry there?
147         if (isset($_SERVER['HTTP_USER_AGENT'])) {
148                 // Then use it securely
149                 $ua = crackerTrackerSecureString(urldecode($_SERVER['HTTP_USER_AGENT']));
150         }
151
152         // Sanitize it?
153         if ($sanitize === true) {
154                 // Sanitize ...
155                 $ua = crackerTrackerSanitize($ua);
156         }
157
158         // Return it
159         return $ua;
160 }
161
162 // Detects the script name
163 function crackerTrackerScriptName (bool $sanitize = false) {
164         // Default is NULL
165         $scriptName = NULL;
166
167         // Is it there?
168         if (!empty($_SERVER['SCRIPT_NAME'])) {
169                 // Return NULL
170                 $scriptName = crackerTrackerSecureString($_SERVER['SCRIPT_NAME']);
171         }
172
173         // Sanitize it?
174         if ($sanitize === true) {
175                 // Sanitize ...
176                 $scriptName = crackerTrackerSanitize($scriptName);
177         }
178
179         // Return
180         return $scriptName;
181 }
182
183 // Detects the query string
184 function crackerTrackerQueryString (bool $sanitize = false) {
185         // Default is NULL
186         $query = NULL;
187
188         // Is it there?
189         if (!empty($_SERVER['QUERY_STRING'])) {
190                 // Get string escaped
191                 $query = crackerTrackerEscapeString(urldecode($_SERVER['QUERY_STRING']));
192         } elseif (!empty($_SERVER['REQUEST_URI'])) {
193                 // Get string escaped
194                 $query = crackerTrackerEscapeString(urldecode($_SERVER['REQUEST_URI']));
195         }
196
197         // Sanitize it?
198         if ((!empty($query)) && ($sanitize === true)) {
199                 // Sanitize ...
200                 $query = crackerTrackerSanitize($query);
201         }
202
203         // Return it
204         return $query;
205 }
206
207 // Detects the server's name
208 function crackerTrackerServerName (bool $sanitize = false) {
209         // Default is NULL
210         $serverName = NULL;
211
212         // Is it there?
213         if (!empty($_SERVER['SERVER_NAME'])) {
214                 // Return NULL
215                 $serverName = crackerTrackerSecureString($_SERVER['SERVER_NAME']);
216         }
217
218         // Sanitize it?
219         if ($sanitize === true) {
220                 // Sanitize ...
221                 $serverName = crackerTrackerSanitize($serverName);
222         }
223
224         // Return it
225         return $serverName;
226 }
227
228 // Detects the referer
229 function crackerTrackerReferer (bool $sanitize = false) {
230         // Default is a dash
231         $referer = '-';
232
233         // Is it there?
234         if (!empty($_SERVER['HTTP_REFERER'])) {
235                 // Then use it securely
236                 $referer = crackerTrackerSecureString(urldecode($_SERVER['HTTP_REFERER']));
237         }
238
239         // Sanitize it?
240         if ($sanitize === true) {
241                 // Sanitize ...
242                 $referer = crackerTrackerSanitize($referer);
243         }
244
245         // Return it
246         return $referer;
247 }
248
249 // Detects request method
250 function crackerTrackerRequestMethod () {
251         // Default is NULL
252         $method = NULL;
253
254         // Is it set?
255         if (!empty($_SERVER['REQUEST_METHOD'])) {
256                 // Then use it
257                 $method = $_SERVER['REQUEST_METHOD'];
258         }
259
260         // Return it
261         return $method;
262 }
263
264 // Detects the scripts path
265 function crackerTrackerScriptPath () {
266         // Should always be there!
267         $path = dirname(crackerTrackerScriptName()) . '/';
268
269         // Return detected path
270         return $path;
271 }
272
273 // Detects wether we have SSL
274 function crackerTrackerSecured () {
275         // Detect it
276         $ssl = ((isset($_SERVER['HTTPS'])) && ($_SERVER['HTTPS'] != 'off'));
277
278         // Return result
279         return $ssl;
280 }
281
282 // Secures a string by escaping it and passing it through strip_tags,htmlentities-chain
283 function crackerTrackerSecureString ($str) {
284         // First escape it
285         $str = crackerTrackerEscapeString($str);
286
287         // Then pass it through the functions
288         $str = htmlentities(strip_tags($str), ENT_QUOTES);
289
290         // Return it
291         return $str;
292 }
293
294 // Is the file there and readable?
295 function isCrackerTrackerFileFound ($FQFN) {
296         // Simply check it
297         return ((file_exists($FQFN)) && (is_readable($FQFN)));
298 }
299
300 // Loads a given "template" (this is more an include file)
301 function crackerTrackerLoadTemplate ($template) {
302         // Create the full-qualified filename (FQFN)
303         $FQFN = sprintf('%s/libs/templates/%s.tpl.php',
304                 $GLOBALS['ctracker_base_path'],
305                 $template
306         );
307
308         // Is this template found?
309         if (isCrackerTrackerFileFound($FQFN)) {
310                 // Detect language
311                 crackerTrackerLanguage();
312
313                 // Load it
314                 require_once($FQFN);
315         } else {
316                 // Not found, so die here
317                 crackerTrackerDie();
318         }
319 }
320
321 // Loads a given "template" (this is more an include file)
322 function crackerTrackerLoadLocalizedTemplate ($template) {
323         // Create the full-qualified filename (FQFN)
324         $FQFN = sprintf('%s/libs/templates/%s/%s.tpl.php',
325                 $GLOBALS['ctracker_base_path'],
326                 getCrackerTrackerLanguage(),
327                 $template
328         );
329
330         // Is this template found?
331         if (isCrackerTrackerFileFound($FQFN)) {
332                 // Load it
333                 require_once($FQFN);
334         } else {
335                 // Not found, so die here
336                 crackerTrackerDie();
337         }
338 }
339
340 // Detects the browser's language file and tries to load it, fall-back on english!
341 function crackerTrackerLanguage () {
342         // Default is English
343         $GLOBALS['ctracker_language'] = 'en';
344         $weight = 1;
345
346         // Is the language string there?
347         if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
348                 // Then detect it
349                 foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $lang) {
350                         // Split it again for q=x.x value
351                         $langArray = explode(';', $lang);
352
353                         // If there is an entry, we have a weight
354                         if ((isset($langArray[1])) && ($langArray[1] > $weight)) {
355                                 // Use this language/weight instead
356                                 $GLOBALS['ctracker_language'] = $langArray[0];
357                                 $weight   = $langArray[1];
358                         }
359                 }
360         }
361
362         // Construct FQFN
363         $FQFN = sprintf('%s/libs/language/%s.php',
364                 $GLOBALS['ctracker_base_path'],
365                 getCrackerTrackerLanguage()
366         );
367
368         // Is it not there, switch to "en"
369         if ((getCrackerTrackerLanguage() != 'en') && (!isCrackerTrackerFileFound($FQFN))) {
370                 // English is default!
371                 $GLOBALS['ctracker_language'] = 'en';
372
373                 // Construct FQFN again
374                 $FQFN = sprintf('%s/libs/language/en.php', $GLOBALS['ctracker_base_path']);
375         }
376
377         // Load the language file
378         require($FQFN);
379 }
380
381 // Loads a given email template and passes through $content
382 function crackerTrackerLoadEmailTemplate ($template, array $content = [], $language = NULL) {
383         // Init language
384         crackerTrackerLanguage();
385
386         // Generate the FQFN
387         $FQFN = sprintf('%s/libs/mails/%s/%s.tpl',
388                 $GLOBALS['ctracker_base_path'],
389                 getCrackerTrackerLanguage($language),
390                 $template
391         );
392
393         // So is the file there?
394         if (isCrackerTrackerFileFound($FQFN)) {
395                 // Init result
396                 $result = 'No result from template ' . $template . '. Please report this at http://forum.shipsimu.org Thank you.';
397
398                 // Then load it
399                 //* DEBUG-DIE: */ die('<pre>$result = "' . crackerTrackerCompileCode(trim(file_get_contents($FQFN))) . '";</pre>');
400                 eval('$result = "' . crackerTrackerCompileCode(trim(file_get_contents($FQFN))) . '";');
401
402                 // Return the result
403                 return $result;
404         } else {
405                 // Not found
406                 crackerTrackerDie();
407         }
408 }
409
410 // Getter for message
411 function getCrackerTrackerLocalized ($message) {
412         // Default message
413         $output = '!' . $message . '!';
414
415         // Is the language string there?
416         if (isset($GLOBALS['ctracker_localized'][$message])) {
417                 // Use this instead
418                 $output = $GLOBALS['ctracker_localized'][$message];
419         }
420
421         // Return it
422         return $output;
423 }
424
425 // Tries to find a message and outputs it
426 function crackerTrackerOutputLocalized ($message) {
427         // Output it
428         print getCrackerTrackerLocalized($message);
429 }
430
431 // Compiles the given code
432 function crackerTrackerCompileCode ($code) {
433         // Find all $content[foo]
434         preg_match_all('/\$(content|GLOBALS)((\[([a-zA-Z0-9-_]+)\])*)/', $code, $matches);
435
436         // Replace " with {QUOTE}
437         $code = str_replace('"', '{QUOTE}', $code);
438
439         // Replace all
440         foreach ($matches[0] as $key=>$match) {
441                 // Replace it
442                 if (substr($match, 0, 8) == '$GLOBALS') {
443                         // $GLOBALS
444                         $code = str_replace($match, "\" . \$GLOBALS['" . $matches[4][$key] . "'] . \"", $code);
445                 } elseif (substr($match, 0, 8) == '$content') {
446                         // $content
447                         $code = str_replace($match, "\" . \$content['" . $matches[4][$key] . "'] . \"", $code);
448                 }
449         }
450
451         // Return it
452         return $code;
453 }
454
455 // "Getter" for language
456 function getCrackerTrackerLanguage ($lang = NULL) {
457         // Default is from browser
458         $language = $GLOBALS['ctracker_language'];
459
460         // Is $lang set?
461         if (!is_null($lang)) {
462                 // Then use this instead
463                 $language = $lang;
464         }
465
466         // Return it
467         return $language;
468 }
469
470 // "Getter" for ticket id
471 function getCrackerTrackerTicketId () {
472         // Default is zero
473         $id = 0;
474
475         // Is it set?
476         if (isset($GLOBALS['ctracker_last_ticket']['ctracker_ticket'])) {
477                 // Then use it
478                 $id = $GLOBALS['ctracker_last_ticket']['ctracker_ticket'];
479         }
480
481         // Return the number
482         return $id;
483 }
484
485 // Sends a cookie to the user that he would not see this security warning again
486 function sendCrackerTrackerCookie () {
487         // Set the cookie
488         // @TODO Why can't domain be set to value from crackerTrackerServerName() ?
489         setcookie('ctracker_ticket', getCrackerTrackerTicketId(), (time() + 60*60*24), '/', '', crackerTrackerSecured(), true);
490         $_COOKIE['ctracker_ticket'] = getCrackerTrackerTicketId();
491 }
492
493 // Is the cookie set?
494 function ifCrackerTrackerCookieIsSet () {
495         // Is it set and valid?
496         return ((isset($_COOKIE['ctracker_ticket'])) && ($_COOKIE['ctracker_ticket'] > 0));
497 }
498
499 // Redirects to the same URL
500 function crackerTrackerRedirectSameUrl () {
501         // Construct and redirect to same URL
502         crackerTrackerSendRawRedirect(sprintf('%s://%s%s?%s',
503                 (crackerTrackerSecured() ? 'https' : 'http'),
504                 crackerTrackerServerName(),
505                 crackerTrackerScriptName(),
506                 crackerTrackerQueryString()
507         ));
508 }
509
510 /**
511  * Send a HTTP redirect to the browser. This function was taken from DokuWiki
512  * (GNU GPL 2; http://www.dokuwiki.org) and modified to fit into this script.
513  *
514  * Works arround Microsoft IIS cookie sending bug. Does exit the script.
515  *
516  * @link    http://support.microsoft.com/kb/q176113/
517  * @author  Andreas Gohr <andi@splitbrain.org>
518  */
519 function crackerTrackerSendRawRedirect ($url) {
520         // Better remove any data by ctracker
521         unsetCtrackerData();
522
523         // always close the session
524         session_write_close();
525
526         // Revert entity &amp;
527         $url = str_replace('&amp;', '&', $url);
528
529         // check if running on IIS < 6 with CGI-PHP
530         if ((isset($_SERVER['SERVER_SOFTWARE'])) && (isset($_SERVER['GATEWAY_INTERFACE'])) &&
531                 (strpos($_SERVER['GATEWAY_INTERFACE'],'CGI') !== false) &&
532                 (preg_match('|^Microsoft-IIS/(\d)\.\d$|', trim($_SERVER['SERVER_SOFTWARE']), $matches)) &&
533                 ($matches[1] < 6)) {
534                 // Send the IIS header
535                 header('Refresh: 0;url=' . $url);
536         } else {
537                 // Send generic header
538                 header('Location: ' . $url);
539         }
540         exit();
541 }
542
543 // Removes all ctracker-related data from global space
544 function unsetCtrackerData () {
545         // Debug message
546         //* DEBUG: */ error_log(__FUNCTION__ . ': CALLED!');
547
548         // Unset all ctracker data
549         foreach (array(
550                         'ctracker_base_path',
551                         'ctracker_host',
552                         'ctracker_dbname',
553                         'ctracker_user',
554                         'ctracker_password',
555                         'ctracker_debug_enabled',
556                         'ctracker_email',
557                         'ctracker_whitelist',
558                         'ctracker_get_blacklist',
559                         'ctracker_post_blacklist',
560                         'ctracker_header',
561                         'ctracker_post_track',
562                         'ctracker_checked_get',
563                         'ctracker_checked_post',
564                         'ctracker_checked_ua',
565                         'ctracker_last_sql',
566                         'ctracker_last_result',
567                         'ctracker_config',
568                         'ctracker_updates',
569                         'ctracker_language',
570                         'ctracker_localized',
571                         'ctracker_link',
572                         'ctracker_blocked_methods',
573                 ) as $key) {
574                         // Unset it
575                         unset($GLOBALS[$key]);
576         }
577 }
578
579 // Sanitizes string
580 function crackerTrackerSanitize ($str) {
581         return str_replace(array('//', '/./'), array('/', '/'), $str);
582 }
583
584 function crackerTrackerIsConsole () {
585         return (php_sapi_name() == 'cli');
586 }
587
588 function ctrackerAntiSpamField () {
589         // Get all fields
590         $fields = ctrackerGetAntiSpamFields();
591
592         // Choose random
593         $fieldName = $fields[mt_rand(0, count($fields) - 1)];
594
595         // Return it
596         return $fieldName;
597 }
598
599 function ctrackerGetAntiSpamFields () {
600         return [
601                 'ctracker_url',
602                 'ctracker_aol',
603                 'ctracker_yahoo',
604                 'ctracker_icq',
605                 'ctracker_jabber',
606         ];
607 }
608
609 function ifCtrackerTrackerAntiSpamFieldGiven () {
610         // Is request method POST?
611         if (crackerTrackerRequestMethod() != 'POST') {
612                 // Cannot be given
613                 return false;
614         }
615
616         // Walk through all fields
617         foreach (ctrackerGetAntiSpamFields() as $fieldName) {
618                 // Is one found?
619                 if (in_array($fieldName, $_POST) && !empty($_POST[$fieldName])) {
620                         // Filled out!
621                         return true;
622                 }
623         }
624 }