6e7fc62ea8ef653a296d0cdaae4a2dd616bc03c6
[ctracker.git] / libs / lib_general.php
1 <?php
2 /**
3  * General functions library
4  *
5  * @author              Roland Haeder <webmaster@ship-simu.org>
6  * @version             3.0.0
7  * @copyright   Copyright (c) 2009, 2010 Cracker Tracker Team
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.ship-simu.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 if (!function_exists('implode_r')) {
26         // Implode recursive a multi-dimension array, taken from www.php.net
27         function implode_r ($glue, $array, $array_name = NULL) {
28                 $return = array();
29                 while(list($key,$value) = @each($array)) {
30                         if(is_array($value)) {
31                                 // Is an array again, so call recursive
32                                 $return[] = implode_r($glue, $value, (string) $key);
33                         } else {
34                                 if($array_name != NULL) {
35                                         $return[] = $array_name . '[' . (string) $key . ']=' . $value . "\n";
36                                 } else {
37                                         $return[] = $key . '=' . $value."\n";
38                                 }
39                         }
40                 } // END - while
41
42                 // Return resulting array
43                 return(implode($glue, $return));
44         } // END - function
45 } // END - if
46
47 if (!function_exists('implode_secure')) {
48         // Implode a simple array with a 'call-back' to our escaper function
49         function implode_secure ($array) {
50                 // Return string
51                 $return = '';
52
53                 // Implode all data
54                 foreach ($array as $entry) {
55                         // Don't escape some
56                         if (in_array($entry, array('NOW()'))) {
57                                 // Add it with non-string glue
58                                 $return .= $entry . ',';
59                         } elseif (empty($entry)) {
60                                 // Empty strings need no escaping
61                                 $return .= '"",';
62                         } else {
63                                 // Secure this string and add it
64                                 $return .= '"' . crackerTrackerEscapeString($entry) . '",';
65                         }
66                 } // END - foreach
67
68                 // Remove last char
69                 $return = substr($return, 0, -1);
70
71                 // Return this string
72                 return $return;
73         } // END - function
74 } // END - if
75
76 // Getter for ctracker_debug_enabled
77 function isCrackerTrackerDebug () {
78         // Is it set?
79         return ((isset($GLOBALS['ctracker_debug_enabled'])) && ($GLOBALS['ctracker_debug_enabled'] === true));
80 }
81
82 // Determines the real remote address
83 function determineCrackerTrackerRealRemoteAddress () {
84         // Is a proxy in use?
85         if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
86                 // Proxy was used
87                 $address = $_SERVER['HTTP_X_FORWARDED_FOR'];
88         } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
89                 // Yet, another proxy
90                 $address = $_SERVER['HTTP_CLIENT_IP'];
91         } else {
92                 // The regular address when no proxy was used
93                 $address = $_SERVER['REMOTE_ADDR'];
94         }
95
96         // This strips out the real address from proxy output
97         if (strstr($address, ',')) {
98                 $addressArray = explode(',', $address);
99                 $address = $addressArray[0];
100         } // END - if
101
102         // Return the result
103         return $address;
104 }
105
106 // Determine if a proxy was used
107 function isCrackerTrackerProxyUsed () {
108         // Check if specific entries are set
109         $proxyUsed = ((isset($_SERVER['HTTP_X_FORWARDED_FOR'])) || (isset($_SERVER['HTTP_CLIENT_IP'])));
110
111         // Return result
112         return $proxyUsed;
113 }
114
115 // Detects the user-agent string
116 function crackerTrackerUserAgent () {
117         // Default is 'unknown'
118         $ua = 'unknown';
119
120         // Is the entry there?
121         if (isset($_SERVER['HTTP_USER_AGENT'])) {
122                 // Then use it securely
123                 $ua = crackerTrackerSecureString($_SERVER['HTTP_USER_AGENT']);
124         } // END - if
125
126         // Return it
127         return $ua;
128 }
129
130 // Detects the script name
131 function crackerTrackerScriptName () {
132         // Should always be there!
133         return crackerTrackerSecureString($_SERVER['SCRIPT_NAME']);
134 }
135
136 // Detects the query string
137 function crackerTrackerQueryString () {
138         // Should always be there!
139         return crackerTrackerEscapeString($_SERVER['QUERY_STRING']);
140 }
141
142 // Detects the server's name
143 function crackerTrackerServerName () {
144         // Should always be there!
145         return crackerTrackerSecureString($_SERVER['SERVER_NAME']);
146 }
147
148 // Detects the referer
149 function crackerTrackerReferer () {
150         // Default is a dash
151         $referer = '-';
152
153         // Is it there?
154         if (isset($_SERVER['HTTP_REFERER'])) {
155                 // Then use it securely
156                 $referer = crackerTrackerSecureString($_SERVER['HTTP_REFERER']);
157         } // END - if
158
159         // Return it
160         return $referer;
161 }
162
163 // Detects the scripts path
164 function crackerTrackerScriptPath () {
165         // Should always be there!
166         $path = dirname(crackerTrackerScriptName()) . '/';
167
168         // Return detected path
169         return $path;
170 }
171
172 // Detects wether we have SSL
173 function crackerTrackerSecured () {
174         // Detect it
175         $ssl = ((isset($_SERVER['HTTPS'])) && ($_SERVER['HTTPS'] != 'off'));
176
177         // Return result
178         return $ssl;
179 }
180
181 // Secures a string by escaping it and passing it through strip_tags,htmlentities-chain
182 function crackerTrackerSecureString ($str) {
183         // First escape it
184         $str = crackerTrackerEscapeString($str);
185
186         // Then pass it through the functions
187         $str = htmlentities(strip_tags($str), ENT_QUOTES);
188
189         // Return it
190         return $str;
191 }
192
193 // Is the file there and readable?
194 function isCrackerTrackerFileFound ($FQFN) {
195         // Simply check it
196         return ((file_exists($FQFN)) && (is_readable($FQFN)));
197 }
198
199 // Loads a given "template" (this is more an include file)
200 function crackerTrackerLoadTemplate ($template) {
201         // Create the full-qualified filename (FQFN)
202         $FQFN = sprintf("%s/templates/%s.tpl.php",
203                 dirname(__FILE__),
204                 $template
205         );
206
207         // Is this template found?
208         if (isCrackerTrackerFileFound($FQFN)) {
209                 // Detect language
210                 crackerTrackerLanguage();
211
212                 // Load it
213                 require_once($FQFN);
214         } else {
215                 // Not found, so die here
216                 crackerTrackerDie();
217         }
218 }
219
220 // Loads a given "template" (this is more an include file)
221 function crackerTrackerLoadLocalizedTemplate ($template) {
222         // Create the full-qualified filename (FQFN)
223         $FQFN = sprintf("%s/templates/%s/%s.tpl.php",
224                 dirname(__FILE__),
225                 getCrackerTrackerLanguage(),
226                 $template
227         );
228
229         // Is this template found?
230         if (isCrackerTrackerFileFound($FQFN)) {
231                 // Load it
232                 require_once($FQFN);
233         } else {
234                 // Not found, so die here
235                 crackerTrackerDie();
236         }
237 }
238
239 // Detects the browser's language file and tries to load it, fall-back on english!
240 function crackerTrackerLanguage () {
241         // Default is English
242         $GLOBALS['ctracker_language'] = 'en';
243         $weight = 1;
244
245         // Is the language string there?
246         if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
247                 // Then detect it
248                 foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $lang) {
249                         // Split it again for q=x.x value
250                         $langArray = explode(';', $lang);
251
252                         // If there is an entry, we have a weight
253                         if ((isset($langArray[1])) && ($langArray[1] > $weight)) {
254                                 // Use this language/weight instead
255                                 $GLOBALS['ctracker_language'] = $langArray[0];
256                                 $weight   = $langArray[1];
257                         } // END - if
258                 } // END - foreach
259         } // END - if
260
261         // Construct FQFN
262         $FQFN = sprintf("%s/language/%s.php",
263                 dirname(__FILE__),
264                 getCrackerTrackerLanguage()
265         );
266
267         // Is it not there, switch to "en"
268         if ((getCrackerTrackerLanguage() != 'en') && (!isCrackerTrackerFileFound($FQFN))) {
269                 // English is default!
270                 $GLOBALS['ctracker_language'] = 'en';
271
272                 // Construct FQFN again
273                 $FQFN = sprintf("%s/language/en.php",
274                         dirname(__FILE__)
275                 );
276         } // END - if
277
278         // Load the language file
279         require($FQFN);
280 }
281
282 // Loads a given email template and passes through $content
283 function crackerTrackerLoadEmailTemplate ($template, array $content = array(), $language = null) {
284         // Init language
285         crackerTrackerLanguage();
286
287         // Generate the FQFN
288         $FQFN = sprintf("%s/mails/%s/%s.tpl",
289                 dirname(__FILE__),
290                 getCrackerTrackerLanguage($language),
291                 $template
292         );
293
294         // So is the file there?
295         if (isCrackerTrackerFileFound($FQFN)) {
296                 // Init result
297                 $result = 'No result from template ' . $template . '. Please report this at http://forum.ship-simu.org Thank you.';
298
299                 // Then load it
300                 eval('$result = "' . crackerTrackerCompileCode(file_get_contents($FQFN)) . '";');
301
302                 // Return the result
303                 return $result;
304         } else {
305                 // Not found
306                 crackerTrackerDie();
307         }
308 }
309
310 // Getter for message
311 function getCrackerTrackerLocalized ($message) {
312         // Default message
313         $output = '!' . $message . '!';
314
315         // Is the language string there?
316         if (isset($GLOBALS['ctracker_localized'][$message])) {
317                 // Use this instead
318                 $output = $GLOBALS['ctracker_localized'][$message];
319         } // END - if
320
321         // Return it
322         return $output;
323 }
324
325 // Tries to find a message and outputs it
326 function crackerTrackerOutputLocalized ($message) {
327         // Output it
328         print getCrackerTrackerLocalized($message);
329 }
330
331 // Compiles the given code
332 function crackerTrackerCompileCode ($code) {
333         // Find all $content[foo]
334         preg_match_all('/\$(content|GLOBALS)((\[([a-zA-Z0-9-_]+)\])*)/', $code, $matches);
335
336         // Replace " with {QUOTE}
337         $code = str_replace('"', '{QUOTE}', $code);
338
339         // Replace all
340         foreach ($matches[0] as $key=>$match) {
341                 // Replace it
342                 if (substr($match, 0, 8) == '$GLOBALS') {
343                         // $GLOBALS
344                         $code = str_replace($match, "\" . \$GLOBALS['" . $matches[4][$key] . "'] . \"", $code);
345                 } elseif (substr($match, 0, 8) == '$content') {
346                         // $content
347                         $code = str_replace($match, "\" . \$content['" . $matches[4][$key] . "'] . \"", $code);
348                 }
349         } // END - foreach
350
351         // Return it
352         return $code;
353 }
354
355 // "Getter" for language
356 function getCrackerTrackerLanguage ($lang = null) {
357         // Default is from browser
358         $language = $GLOBALS['ctracker_language'];
359
360         // Is $lang set?
361         if (!is_null($lang)) {
362                 // Then use this instead
363                 $language = $lang;
364         } // END - if
365
366         // Return it
367         return $language;
368 }
369
370 // "Getter" for ticket id
371 function getCrackerTrackerTicketId () {
372         // Default is zero
373         $id = 0;
374
375         // Is it set?
376         if (isset($GLOBALS['ctracker_last_ticket']['ctracker_ticket'])) {
377                 // Then use it
378                 $id = $GLOBALS['ctracker_last_ticket']['ctracker_ticket'];
379         } // END - if
380
381         // Return the number
382         return $id;
383 }
384
385 // Sends a cookie to the user that he would not see this security warning again
386 function sendCrackerTrackerCookie () {
387         // Set the cookie
388         // @TODO Why can't domain be set to value from crackerTrackerServerName() ?
389         setcookie('ctracker_ticket', getCrackerTrackerTicketId(), (time() + 60*60*24), '/', '', crackerTrackerSecured(), true);
390         $_COOKIE['ctracker_ticket'] = getCrackerTrackerTicketId();
391 }
392
393 // Is the cookie set?
394 function ifCrackerTrackerCookieIsSet () {
395         // Is it set and valid?
396         return ((isset($_COOKIE['ctracker_ticket'])) && ($_COOKIE['ctracker_ticket'] > 0));
397 }
398
399 // Redirects to the same URL
400 function crackerTrackerRedirectSameUrl () {
401         // Construct the url
402         $url = '://' . crackerTrackerServerName() . crackerTrackerScriptName() . '?' . crackerTrackerQueryString();
403
404         // Do we have SSL?
405         if (crackerTrackerSecured()) {
406                 // HTTPS
407                 $url = 'https' . $url;
408         } else {
409                 // HTTP
410                 $url = 'http' . $url;
411         }
412
413         // And redirect
414         crackerTrackerSendRawRedirect($url);
415 }
416
417 /**
418  * Send a HTTP redirect to the browser. This function wass taken from DokuWiki
419  * (GNU GPL 2; http://www.dokuwiki.org) and modified to fit into this script.
420  *
421  * ----------------------------------------------------------------------------
422  * If you want to redirect, please use redirectToUrl(); instead
423  * ----------------------------------------------------------------------------
424  *
425  * Works arround Microsoft IIS cookie sending bug. Does exit the script.
426  *
427  * @link    http://support.microsoft.com/kb/q176113/
428  * @author  Andreas Gohr <andi@splitbrain.org>
429  * @access  private
430  */
431 function crackerTrackerSendRawRedirect ($url) {
432         // always close the session
433         session_write_close();
434
435         // Revert entity &amp;
436         $url = str_replace('&amp;', '&', $url);
437
438         // check if running on IIS < 6 with CGI-PHP
439         if ((isset($_SERVER['SERVER_SOFTWARE'])) && (isset($_SERVER['GATEWAY_INTERFACE'])) &&
440                 (strpos($_SERVER['GATEWAY_INTERFACE'],'CGI') !== false) &&
441                 (preg_match('|^Microsoft-IIS/(\d)\.\d$|', trim($_SERVER['SERVER_SOFTWARE']), $matches)) &&
442                 ($matches[1] < 6)) {
443                 // Send the IIS header
444                 header('Refresh: 0;url=' . $url);
445         } else {
446                 // Send generic header
447                 header('Location: ' . $url);
448         }
449         exit();
450 }
451
452 // [EOF]
453 ?>