1 | <?php
|
---|
2 | /*
|
---|
3 | $Id: common.php 2275 2009-08-21 20:11:41Z andrewsimpson $
|
---|
4 |
|
---|
5 | (c) 2002 - 2009 Andrew Simpson <andrew.simpson at paradise.net.nz>
|
---|
6 |
|
---|
7 | WebCollab
|
---|
8 | ---------------------------------------
|
---|
9 |
|
---|
10 | This program is free software; you can redistribute it and/or modify it under the
|
---|
11 | terms of the GNU General Public License as published by the Free Software Foundation;
|
---|
12 | either version 2 of the License, or (at your option) any later version.
|
---|
13 |
|
---|
14 | This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
---|
15 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
---|
16 | PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
---|
17 |
|
---|
18 | You should have received a copy of the GNU General Public License along with this
|
---|
19 | program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
---|
20 | Cambridge, MA 02139, USA.
|
---|
21 |
|
---|
22 | Function:
|
---|
23 | ---------
|
---|
24 |
|
---|
25 | Common functions library
|
---|
26 |
|
---|
27 | */
|
---|
28 |
|
---|
29 | //
|
---|
30 | // Input validation (single line input)
|
---|
31 | //
|
---|
32 | function safe_data($body ) {
|
---|
33 |
|
---|
34 | //remove excess whitespace
|
---|
35 | $body = trim($body);
|
---|
36 |
|
---|
37 | //return null for nothing input
|
---|
38 | if(strlen($body) == 0 ) {
|
---|
39 | return '';
|
---|
40 | }
|
---|
41 |
|
---|
42 | //validate characters
|
---|
43 | $body = validate($body);
|
---|
44 |
|
---|
45 | //limit line length for single line entries
|
---|
46 | if(strlen($body ) > 100 ) {
|
---|
47 | if(UNICODE_VERSION == 'Y' ) {
|
---|
48 | $body = mb_strimwidth($body, 0, 100, '...' );
|
---|
49 | }
|
---|
50 | else {
|
---|
51 | $body = substr($body, 0, 100 );
|
---|
52 | }
|
---|
53 | }
|
---|
54 |
|
---|
55 | //remove line breaks (not allowed in single lines!)
|
---|
56 | $body = strtr($body, array("\r"=>' ', "\n"=>' ' ) );
|
---|
57 | //add HTML entities
|
---|
58 | $body = html_clean_up($body);
|
---|
59 | //prevent SQL injection
|
---|
60 | $body = db_escape_string($body );
|
---|
61 |
|
---|
62 | return $body;
|
---|
63 | }
|
---|
64 |
|
---|
65 | //
|
---|
66 | // Input validation (multiple line input)
|
---|
67 | //
|
---|
68 | function safe_data_long($body ) {
|
---|
69 |
|
---|
70 | //remove excess whitespace
|
---|
71 | $body = trim($body);
|
---|
72 |
|
---|
73 | //return null for nothing input
|
---|
74 | if(strlen($body) == 0 ) {
|
---|
75 | return '';
|
---|
76 | }
|
---|
77 |
|
---|
78 | //validate characters
|
---|
79 | $body = validate($body);
|
---|
80 |
|
---|
81 | //normalise line breaks from Windows & Mac to UNIX style '\n'
|
---|
82 | $body = str_replace("\r\n", "\n", $body );
|
---|
83 | $body = str_replace("\r", "\n", $body );
|
---|
84 | //break up long non-wrap words
|
---|
85 | $pattern_modifier = (UNICODE_VERSION == 'Y' ) ? 'u' : '';
|
---|
86 | $body = preg_replace("/[^\s\n\t]{100}/".$pattern_modifier, "$0\n", $body );
|
---|
87 | //add HTML entities
|
---|
88 | $body = html_clean_up($body);
|
---|
89 | //prevent SQL injection
|
---|
90 | $body = db_escape_string($body );
|
---|
91 |
|
---|
92 | return $body;
|
---|
93 | }
|
---|
94 |
|
---|
95 | function validate($body ) {
|
---|
96 |
|
---|
97 | //we don't use magic_quotes
|
---|
98 | if(get_magic_quotes_gpc() ) {
|
---|
99 | $body = stripslashes($body );
|
---|
100 | }
|
---|
101 |
|
---|
102 | if(UNICODE_VERSION == 'Y' || CHARACTER_SET == 'UTF-8' ) {
|
---|
103 |
|
---|
104 | $body = preg_replace('/[\x00-\x08\x10\x0B\x0C\x0E-\x19\x7F]'. //ASCII
|
---|
105 | '|[\x00-\x7F][\x80-\xBF]+'. //continuation with no start
|
---|
106 | '|[\xC0-\xDF]((?![\x80-\xBF])|[\x80-\xBF]{2,})'. //illegal two byte
|
---|
107 | '|[\xE0-\xEF](([\x80-\xBF](?![\x80-\xBF]))|(?![\x80-\xBF]{2})|[\x80-\xBF]{3,})'. //illegal three byte
|
---|
108 | '|[\xF0-\xFF][\x80-\xBF]*/', //reject more than 3 byte
|
---|
109 | '?', $body );
|
---|
110 |
|
---|
111 | $body = preg_replace('/[\xC0\xC1][\x80-\xBF]'. //exclude two byte over longs
|
---|
112 | '|\xE0[\x80-\x9F][\x80-\xBF]'. //exclude three byte over longs
|
---|
113 | '|\xED[\xA0-\xBF][\x80-\xBF]/','?', $body ); //exclude surrogates
|
---|
114 |
|
---|
115 | }
|
---|
116 | else {
|
---|
117 | //Single byte validation regex
|
---|
118 | // allow only normal printing characters valid for the character set in use
|
---|
119 | // character set regex in language file
|
---|
120 | $body = preg_replace(VALIDATION_REGEX, '?', $body );
|
---|
121 | }
|
---|
122 |
|
---|
123 | return $body;
|
---|
124 | }
|
---|
125 |
|
---|
126 | function html_clean_up($body ) {
|
---|
127 |
|
---|
128 | if(version_compare(PHP_VERSION, '5.2.3', '>=' ) ) {
|
---|
129 | $body = @htmlspecialchars($body, ENT_QUOTES, CHARACTER_SET, false );
|
---|
130 |
|
---|
131 | }
|
---|
132 | else {
|
---|
133 | //change '&' to '&' except when part of an entity, or already changed
|
---|
134 | if(! strpos($body, '&' ) === false ) {
|
---|
135 | $body = preg_replace('/&(?!(#[\d]{2,5}|amp);)/', '&', $body );
|
---|
136 | }
|
---|
137 | //use HTML for characters that could be used for xss <script>
|
---|
138 | // also convert quotes to HTML for XHTML compliance
|
---|
139 | $trans = array('<'=>'<', '>'=>'>', '"'=>'"', "'"=>''' );
|
---|
140 | $body = strtr($body, $trans );
|
---|
141 | }
|
---|
142 |
|
---|
143 | return $body;
|
---|
144 | }
|
---|
145 |
|
---|
146 | //
|
---|
147 | //check for true positive integer values to max size limits of PHP
|
---|
148 | //
|
---|
149 | function safe_integer($integer ) {
|
---|
150 |
|
---|
151 | if(is_numeric($integer) && ((string)$integer === (string)intval(abs($integer ) ) ) ) {
|
---|
152 | return true;
|
---|
153 | }
|
---|
154 | return false;
|
---|
155 | }
|
---|
156 |
|
---|
157 | //
|
---|
158 | // shorten a character string to 20 characters (to fit a small box)
|
---|
159 | //
|
---|
160 | function box_shorten($body, $len=20 ){
|
---|
161 |
|
---|
162 | $m_strlen = (UNICODE_VERSION == 'Y' ) ? 'mb_strlen' : 'strlen';
|
---|
163 | $m_substr = (UNICODE_VERSION == 'Y' ) ? 'mb_substr' : 'substr';
|
---|
164 |
|
---|
165 | if($m_strlen($body ) > $len ) {
|
---|
166 |
|
---|
167 | //rough cut to fit, then look for word boundaries for better cut
|
---|
168 | $first_cut = $m_substr($body, 0, ($len + 5 ) );
|
---|
169 | $last_space_pos = strrpos($first_cut, ' ' );
|
---|
170 |
|
---|
171 | //adjust to suit word boundary if possible
|
---|
172 | if(($last_space_pos === false ) || ($last_space_pos > ($len - 5 ) ) ) {
|
---|
173 | $len = $last_space_pos;
|
---|
174 | }
|
---|
175 | $body = substr($body, 0, $len );
|
---|
176 | $body .= ' ...';
|
---|
177 | }
|
---|
178 |
|
---|
179 | return $body;
|
---|
180 | }
|
---|
181 |
|
---|
182 | //
|
---|
183 | // single quotes in javascript fields are escaped
|
---|
184 | // double quotes are left as HTML (escaping won't work)
|
---|
185 | //
|
---|
186 | function javascript_escape($body ) {
|
---|
187 |
|
---|
188 | //convert HTML
|
---|
189 | $body = strtr($body, array('''=>"'") );
|
---|
190 | //escape quotes
|
---|
191 | $body = strtr($body, array("'"=>"\\'" ) );
|
---|
192 |
|
---|
193 | return $body;
|
---|
194 | }
|
---|
195 |
|
---|
196 | //
|
---|
197 | // add bbcode tags functionality
|
---|
198 | //
|
---|
199 | function bbcode($body ) {
|
---|
200 |
|
---|
201 | if(strlen($body) == 0 ) {
|
---|
202 | return '';
|
---|
203 | }
|
---|
204 |
|
---|
205 | if(! strpos($body, '@' ) === false ) {
|
---|
206 | //email links
|
---|
207 | $body = preg_replace('/\b[a-z0-9\.\_\-]+@[a-z0-9][a-z0-9\.\-]+\.[a-z\.]+\b/i', "<a href=\"mailto:$0\">$0</a>", $body );
|
---|
208 | }
|
---|
209 |
|
---|
210 | //bbcode tags
|
---|
211 | if(! strpos($body, '[/' ) === false ) {
|
---|
212 | $body = preg_replace('#\[i\](.+?)\[/i\]#i', "<i>$1</i>", $body );
|
---|
213 | $body = preg_replace('#\[b\](.+?)\[/b\]#i', "<b>$1</b>", $body );
|
---|
214 | $body = preg_replace('#\[u\](.+?)\[/u\]#i', "<span style=\"text-decoration: underline;\">$1</span>", $body );
|
---|
215 | $body = preg_replace('#\[quote\](.+?)\[/quote\]#i', "<blockquote><p>$1</p></blockquote>", $body );
|
---|
216 | $body = preg_replace('#\[code\](.+?)\[/code\]#i', "<pre>$1</pre>", $body );
|
---|
217 | $body = preg_replace('#\[color=(red|blue|green|yellow)\](.+?)\[/color\]#i', "<span style=\"color:$1\">$2</span>", $body );
|
---|
218 | $body = preg_replace('#\[img\](http(s)?:\/\/([a-z0-9\-_~/.])+?\.(jpg|jpeg|gif|png))\[/img\]#i', "<img src=\"$1\" alt=\"\"/>", $body );
|
---|
219 | $body = preg_replace_callback('#\[url\]((http|ftp)+(s)?:\/\/[a-z0-9\-_~/@:?=&;+\#.]+)\[/url\]#i', 'link1', $body );
|
---|
220 | $body = preg_replace_callback('#\[url=((http|ftp)+(s)?:\/\/([a-z0-9\-_~.]+[.][a-z]{2,6})[a-z0-9\-_~/@:?=&;+\#.%]*)\](.+?)\[/url\]#i', 'link2', $body );
|
---|
221 | }
|
---|
222 | return $body;
|
---|
223 | }
|
---|
224 |
|
---|
225 | function link1($url) {
|
---|
226 | $url[1] = strtr($url[1], array("&" => "&" ) );
|
---|
227 | $body = "<a href=\"".$url[1]."\" onclick=\"window.open('".$url[1]."'); return false\">".$url[1]."</a>";
|
---|
228 | return $body;
|
---|
229 | }
|
---|
230 |
|
---|
231 | function link2($url) {
|
---|
232 | $url[1] = strtr($url[1], array("&" => "&" ) );
|
---|
233 | $body = "<a href=\"".$url[1]."\" onclick=\"window.open('".$url[1]."'); return false\">".$url[5]."</a> [".$url[4]."]";
|
---|
234 | return $body;
|
---|
235 | }
|
---|
236 |
|
---|
237 | //
|
---|
238 | // Nice format for file size
|
---|
239 | //
|
---|
240 |
|
---|
241 | function nice_size($size ) {
|
---|
242 |
|
---|
243 | if(! $size ) {
|
---|
244 | $size = 0;
|
---|
245 | }
|
---|
246 | elseif($size > (1043741824 ) ) {
|
---|
247 | $size = sprintf('%.2f GB', ($size/(1043741824 ) ) );
|
---|
248 | }
|
---|
249 | elseif($size > (1048576 ) ) {
|
---|
250 | $size = sprintf('%.2f MB', ($size/(1048576 ) ) );
|
---|
251 | }
|
---|
252 | elseif($size > 1024 ) {
|
---|
253 | $size = (sprintf('%d kB', $size/(1024 ) ) );
|
---|
254 | }
|
---|
255 | else {
|
---|
256 | $size = (sprintf('%d B', $size ) );
|
---|
257 | }
|
---|
258 |
|
---|
259 | return $size;
|
---|
260 | }
|
---|
261 |
|
---|
262 | //
|
---|
263 | // Check security token still valid
|
---|
264 | //
|
---|
265 |
|
---|
266 | function token_check($token ) {
|
---|
267 |
|
---|
268 | if((! preg_match('/^[a-f\d]{32}$/i', $token ) ) || $token !== OLD_TOKEN ) {
|
---|
269 | error("Invalid session", "Possible session hijacking detected." );
|
---|
270 | }
|
---|
271 |
|
---|
272 | return true;
|
---|
273 | }
|
---|
274 |
|
---|
275 | //
|
---|
276 | // Builds up an error screen
|
---|
277 | //
|
---|
278 | function error($box_title, $error ) {
|
---|
279 |
|
---|
280 | global $db_error_message;
|
---|
281 |
|
---|
282 | include_once(BASE.'lang/lang.php' );
|
---|
283 | include_once(BASE.'includes/screen.php' );
|
---|
284 |
|
---|
285 | create_top('ERROR', 1 );
|
---|
286 |
|
---|
287 | if(NO_ERROR !== 'Y' ) {
|
---|
288 | $content = "<div style=\"text-align : center\">".$error."</div>";
|
---|
289 | new_box( $box_title, $content, 'boxdata', 'singlebox' );
|
---|
290 | }
|
---|
291 | else {
|
---|
292 | new_box($lang['report'], $lang['warning'], 'boxdata2', 'singlebox' );
|
---|
293 | }
|
---|
294 |
|
---|
295 | if((EMAIL_ERROR != NULL ) || (DEBUG === 'Y' ) ) {
|
---|
296 |
|
---|
297 | $uid_name = defined('UID_NAME') ? UID_NAME : '';
|
---|
298 | $uid_email = defined('UID_EMAIL') ? UID_EMAIL : '';
|
---|
299 | $manager_name = defined('MANAGER_NAME') ? MANAGER_NAME : 'WebCollab';
|
---|
300 |
|
---|
301 | //get the post vars
|
---|
302 | ob_start();
|
---|
303 | print_r($_REQUEST );
|
---|
304 | $post = ob_get_contents();
|
---|
305 | ob_end_clean();
|
---|
306 |
|
---|
307 | //email to the error address
|
---|
308 | $message = "Hello,\n This is the ".$manager_name." site and I have an error :/ \n".
|
---|
309 | "\n\n".
|
---|
310 | "Error message: ".$error."\n".
|
---|
311 | "Database message: ".$db_error_message."\n".
|
---|
312 | "User: ".$uid_name." (".$uid_email.")\n".
|
---|
313 | "Component: ".$box_title."\n".
|
---|
314 | "Page that was called: ".$_SERVER['SCRIPT_NAME']."\n".
|
---|
315 | "Requested URL: ".$_SERVER['REQUEST_URI']."\n".
|
---|
316 | "URL string: ".$_SERVER['QUERY_STRING']."\n".
|
---|
317 | "Browser: ".$_SERVER['HTTP_USER_AGENT']."\n".
|
---|
318 | "Time: ".date("F j, Y, H:i")."\n".
|
---|
319 | "IP: ".$_SERVER['REMOTE_ADDR']."\n".
|
---|
320 | "WebCollab version:".WEBCOLLAB_VERSION."\n".
|
---|
321 | "POST variables: $post\n\n";
|
---|
322 |
|
---|
323 | if(EMAIL_ERROR != NULL ) {
|
---|
324 | include_once(BASE.'includes/email.php' );
|
---|
325 | email(EMAIL_ERROR, "ERROR on ".MANAGER_NAME, $message );
|
---|
326 | }
|
---|
327 |
|
---|
328 | if(DEBUG === 'Y' ) {
|
---|
329 | $content = nl2br($message);
|
---|
330 | new_box("Error Debug", $content );
|
---|
331 | }
|
---|
332 | }
|
---|
333 |
|
---|
334 | create_bottom();
|
---|
335 |
|
---|
336 | //do not return
|
---|
337 | die;
|
---|
338 | }
|
---|
339 |
|
---|
340 | //
|
---|
341 | // Builds up a warning screen
|
---|
342 | //
|
---|
343 | function warning($box_title, $message ) {
|
---|
344 |
|
---|
345 | global $lang;
|
---|
346 |
|
---|
347 | include_once(BASE.'lang/lang.php' );
|
---|
348 | include_once(BASE.'includes/screen.php' );
|
---|
349 |
|
---|
350 | create_top($lang['error'], 1 );
|
---|
351 |
|
---|
352 | $content = "<div style=\"text-align : center\">".$message."</div>\n";
|
---|
353 | new_box($box_title, $content, 'boxdata', 'singlebox' );
|
---|
354 |
|
---|
355 | create_bottom();
|
---|
356 |
|
---|
357 | //do not return
|
---|
358 | die;
|
---|
359 | }
|
---|
360 |
|
---|
361 | ?>
|
---|