1
|
|
|
<?php |
|
|
|
|
2
|
|
|
/** |
3
|
|
|
* Output functions |
4
|
|
|
* Processing text for output such as pulling out URLs and extracting excerpts |
5
|
|
|
* |
6
|
|
|
* @package Elgg |
7
|
|
|
* @subpackage Core |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Takes a string and turns any URLs into formatted links |
12
|
|
|
* |
13
|
|
|
* @param string $text The input string |
14
|
|
|
* |
15
|
|
|
* @return string The output string with formatted links |
16
|
|
|
*/ |
17
|
|
|
function parse_urls($text) { |
18
|
|
|
|
19
|
|
|
$linkify = new \Misd\Linkify\Linkify(); |
20
|
|
|
|
21
|
|
|
return $linkify->processUrls($text, ['attr' => ['rel' => 'nofollow']]); |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Takes a string and turns any email addresses into formatted links |
26
|
|
|
* |
27
|
|
|
* @param string $text The input string |
28
|
|
|
* |
29
|
|
|
* @return string The output string with formatted links |
30
|
|
|
* |
31
|
|
|
* @since 2.3 |
32
|
|
|
*/ |
33
|
|
|
function elgg_parse_emails($text) { |
34
|
|
|
$linkify = new \Misd\Linkify\Linkify(); |
35
|
|
|
|
36
|
|
|
return $linkify->processEmails($text, ['attr' => ['rel' => 'nofollow']]); |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Create paragraphs from text with line spacing |
41
|
|
|
* |
42
|
|
|
* @param string $string The string |
43
|
|
|
* |
44
|
|
|
* @return string |
45
|
|
|
**/ |
46
|
|
|
function elgg_autop($string) { |
47
|
|
|
return _elgg_services()->autoP->process($string); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Returns an excerpt. |
52
|
|
|
* Will return up to n chars stopping at the nearest space. |
53
|
|
|
* If no spaces are found (like in Japanese) will crop off at the |
54
|
|
|
* n char mark. Adds ... if any text was chopped. |
55
|
|
|
* |
56
|
|
|
* @param string $text The full text to excerpt |
57
|
|
|
* @param int $num_chars Return a string up to $num_chars long |
58
|
|
|
* |
59
|
|
|
* @return string |
60
|
|
|
* @since 1.7.2 |
61
|
|
|
*/ |
62
|
|
|
function elgg_get_excerpt($text, $num_chars = 250) { |
63
|
|
|
$view = 'output/excerpt'; |
64
|
|
|
$vars = [ |
65
|
|
|
'text' => $text, |
66
|
|
|
'num_chars' => $num_chars, |
67
|
|
|
]; |
68
|
|
|
$viewtype = elgg_view_exists($view) ? '' : 'default'; |
69
|
|
|
|
70
|
|
|
return _elgg_view_under_viewtype($view, $vars, $viewtype); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Format bytes to a human readable format |
75
|
|
|
* |
76
|
|
|
* @param int $size File size in bytes to format |
77
|
|
|
* |
78
|
|
|
* @param int $precision Precision to round formatting bytes to |
79
|
|
|
* |
80
|
|
|
* @return string |
81
|
|
|
* @since 1.9.0 |
82
|
|
|
*/ |
83
|
|
|
function elgg_format_bytes($size, $precision = 2) { |
84
|
|
|
if (!$size || $size < 0) { |
85
|
|
|
return false; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
$base = log($size) / log(1024); |
89
|
|
|
$suffixes = array('B', 'kB', 'MB', 'GB', 'TB'); |
90
|
|
|
|
91
|
|
|
return round(pow(1024, $base - floor($base)), $precision) . ' ' . $suffixes[floor($base)]; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Converts an associative array into a string of well-formed HTML/XML attributes |
96
|
|
|
* Returns a concatenated string of HTML attributes to be inserted into a tag (e.g., <tag $attrs>) |
97
|
|
|
* |
98
|
|
|
* @see elgg_format_element |
99
|
|
|
* |
100
|
|
|
* @param array $attrs Attributes |
101
|
|
|
* An array of attribute => value pairs |
102
|
|
|
* Attribute value can be a scalar value, an array of scalar values, or true |
103
|
|
|
* <code> |
104
|
|
|
* $attrs = array( |
105
|
|
|
* 'class' => ['elgg-input', 'elgg-input-text'], // will be imploded with spaces |
106
|
|
|
* 'style' => ['margin-left:10px;', 'color: #666;'], // will be imploded with spaces |
107
|
|
|
* 'alt' => 'Alt text', // will be left as is |
108
|
|
|
* 'disabled' => true, // will be converted to disabled="disabled" |
109
|
|
|
* 'data-options' => json_encode(['foo' => 'bar']), // will be output as an escaped JSON string |
110
|
|
|
* 'batch' => <\ElggBatch>, // will be ignored |
111
|
|
|
* 'items' => [<\ElggObject>], // will be ignored |
112
|
|
|
* ); |
113
|
|
|
* </code> |
114
|
|
|
* |
115
|
|
|
* @return string |
116
|
|
|
*/ |
117
|
|
|
function elgg_format_attributes(array $attrs = array()) { |
118
|
7 |
|
if (!is_array($attrs) || empty($attrs)) { |
119
|
|
|
return ''; |
120
|
|
|
} |
121
|
|
|
|
122
|
7 |
|
$attributes = []; |
123
|
|
|
|
124
|
7 |
|
foreach ($attrs as $attr => $val) { |
125
|
7 |
|
if (0 !== strpos($attr, 'data-') && false !== strpos($attr, '_')) { |
126
|
|
|
// this is probably a view $vars variable not meant for output |
127
|
1 |
|
continue; |
128
|
|
|
} |
129
|
|
|
|
130
|
7 |
|
$attr = strtolower($attr); |
131
|
|
|
|
132
|
7 |
|
if (!isset($val) || $val === false) { |
133
|
1 |
|
continue; |
134
|
|
|
} |
135
|
|
|
|
136
|
7 |
|
if ($val === true) { |
137
|
2 |
|
$val = $attr; //e.g. checked => true ==> checked="checked" |
138
|
2 |
|
} |
139
|
|
|
|
140
|
7 |
|
if (is_scalar($val)) { |
141
|
7 |
|
$val = [$val]; |
142
|
7 |
|
} |
143
|
|
|
|
144
|
7 |
|
if (!is_array($val)) { |
145
|
1 |
|
continue; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
// Check if array contains non-scalar values and bail if so |
149
|
|
|
$filtered_val = array_filter($val, function($e) { |
150
|
7 |
|
return is_scalar($e); |
151
|
7 |
|
}); |
152
|
|
|
|
153
|
7 |
|
if (count($val) != count($filtered_val)) { |
154
|
1 |
|
continue; |
155
|
|
|
} |
156
|
|
|
|
157
|
7 |
|
$val = implode(' ', $val); |
158
|
|
|
|
159
|
7 |
|
$val = htmlspecialchars($val, ENT_QUOTES, 'UTF-8', false); |
160
|
7 |
|
$attributes[] = "$attr=\"$val\""; |
161
|
7 |
|
} |
162
|
|
|
|
163
|
7 |
|
return implode(' ', $attributes); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Format an HTML element |
168
|
|
|
* |
169
|
|
|
* @param string|array $tag_name The element tagName. e.g. "div". This will not be validated. |
170
|
|
|
* All function arguments can be given as a single array: The array will be used |
171
|
|
|
* as $attributes, except for the keys "#tag_name", "#text", and "#options", which |
172
|
|
|
* will be extracted as the other arguments. |
173
|
|
|
* |
174
|
|
|
* @param array $attributes The element attributes. This is passed to elgg_format_attributes(). |
175
|
|
|
* |
176
|
|
|
* @param string $text The contents of the element. Assumed to be HTML unless encode_text is true. |
177
|
|
|
* |
178
|
|
|
* @param array $options Options array with keys: |
179
|
|
|
* |
180
|
|
|
* encode_text => (bool, default false) If true, $text will be HTML-escaped. Already-escaped entities |
181
|
|
|
* will not be double-escaped. |
182
|
|
|
* |
183
|
|
|
* double_encode => (bool, default false) If true, the $text HTML escaping will be allowed to double |
184
|
|
|
* encode HTML entities: '×' will become '&times;' |
185
|
|
|
* |
186
|
|
|
* is_void => (bool) If given, this determines whether the function will return just the open tag. |
187
|
|
|
* Otherwise this will be determined by the tag name according to this list: |
188
|
|
|
* http://www.w3.org/html/wg/drafts/html/master/single-page.html#void-elements |
189
|
|
|
* |
190
|
|
|
* is_xml => (bool, default false) If true, void elements will be formatted like "<tag />" |
191
|
|
|
* |
192
|
|
|
* @return string |
193
|
|
|
* @throws InvalidArgumentException |
194
|
|
|
* @since 1.9.0 |
195
|
|
|
*/ |
196
|
|
|
function elgg_format_element($tag_name, array $attributes = array(), $text = '', array $options = array()) { |
197
|
9 |
|
if (is_array($tag_name)) { |
198
|
6 |
|
$args = $tag_name; |
199
|
|
|
|
200
|
6 |
|
if ($attributes !== [] || $text !== '' || $options !== []) { |
201
|
|
|
throw new \InvalidArgumentException('If $tag_name is an array, the other arguments must not be set'); |
202
|
|
|
} |
203
|
|
|
|
204
|
6 |
|
if (isset($args['#tag_name'])) { |
205
|
5 |
|
$tag_name = $args['#tag_name']; |
206
|
5 |
|
} |
207
|
6 |
|
if (isset($args['#text'])) { |
208
|
4 |
|
$text = $args['#text']; |
209
|
4 |
|
} |
210
|
6 |
|
if (isset($args['#options'])) { |
211
|
5 |
|
$options = $args['#options']; |
212
|
5 |
|
} |
213
|
|
|
|
214
|
6 |
|
unset($args['#tag_name'], $args['#text'], $args['#options']); |
215
|
6 |
|
$attributes = $args; |
216
|
6 |
|
} |
217
|
|
|
|
218
|
9 |
|
if (!is_string($tag_name) || $tag_name === '') { |
219
|
1 |
|
throw new \InvalidArgumentException('$tag_name is required'); |
220
|
|
|
} |
221
|
|
|
|
222
|
8 |
|
if (isset($options['is_void'])) { |
223
|
1 |
|
$is_void = $options['is_void']; |
224
|
1 |
|
} else { |
225
|
|
|
// from http://www.w3.org/TR/html-markup/syntax.html#syntax-elements |
226
|
7 |
|
$is_void = in_array(strtolower($tag_name), array( |
227
|
7 |
|
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', |
228
|
7 |
|
'meta', 'param', 'source', 'track', 'wbr' |
229
|
7 |
|
)); |
230
|
|
|
} |
231
|
|
|
|
232
|
8 |
|
if (!empty($options['encode_text'])) { |
233
|
2 |
|
$double_encode = empty($options['double_encode']) ? false : true; |
234
|
2 |
|
$text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8', $double_encode); |
235
|
2 |
|
} |
236
|
|
|
|
237
|
8 |
|
if ($attributes) { |
238
|
4 |
|
$attrs = elgg_format_attributes($attributes); |
239
|
4 |
|
if ($attrs !== '') { |
240
|
4 |
|
$attrs = " $attrs"; |
241
|
4 |
|
} |
242
|
4 |
|
} else { |
243
|
5 |
|
$attrs = ''; |
244
|
|
|
} |
245
|
|
|
|
246
|
8 |
|
if ($is_void) { |
247
|
2 |
|
return empty($options['is_xml']) ? "<{$tag_name}{$attrs}>" : "<{$tag_name}{$attrs} />"; |
248
|
|
|
} else { |
249
|
6 |
|
return "<{$tag_name}{$attrs}>$text</$tag_name>"; |
250
|
|
|
} |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Converts shorthand urls to absolute urls. |
255
|
|
|
* |
256
|
|
|
* No change is made if the URL: is absolute, protocol-relative, starts with a protocol/fragment/query. |
257
|
|
|
* |
258
|
|
|
* @example |
259
|
|
|
* elgg_normalize_url(''); // 'http://my.site.com/' |
260
|
|
|
* elgg_normalize_url('dashboard'); // 'http://my.site.com/dashboard' |
261
|
|
|
* elgg_normalize_url('http://google.com/'); // no change |
262
|
|
|
* elgg_normalize_url('//google.com/'); // no change |
263
|
|
|
* |
264
|
|
|
* @param string $url The URL to normalize |
265
|
|
|
* |
266
|
|
|
* @return string The absolute url |
267
|
|
|
*/ |
268
|
|
|
function elgg_normalize_url($url) { |
269
|
223 |
|
$url = str_replace(' ', '%20', $url); |
270
|
|
|
|
271
|
223 |
|
if (_elgg_sane_validate_url($url)) { |
272
|
58 |
|
return $url; |
273
|
|
|
} |
274
|
|
|
|
275
|
217 |
|
if (preg_match("#^([a-z]+)\\:#", $url, $m)) { |
276
|
|
|
// we don't let http/https: URLs fail filter_var(), but anything else starting with a protocol |
277
|
|
|
// is OK |
278
|
1 |
|
if ($m[1] !== 'http' && $m[1] !== 'https') { |
279
|
1 |
|
return $url; |
280
|
|
|
} |
281
|
|
|
} |
282
|
|
|
|
283
|
216 |
|
if (preg_match("#^(\\#|\\?|//)#", $url)) { |
284
|
|
|
// starts with '//' (protocol-relative link), query, or fragment |
285
|
2 |
|
return $url; |
286
|
|
|
} |
287
|
|
|
|
288
|
214 |
|
if (preg_match("#^[^/]*\\.php(\\?.*)?$#", $url)) { |
289
|
|
|
// root PHP scripts: 'install.php', 'install.php?step=step'. We don't want to confuse these |
290
|
|
|
// for domain names. |
291
|
3 |
|
return elgg_get_site_url() . $url; |
292
|
|
|
} |
293
|
|
|
|
294
|
212 |
|
if (preg_match("#^[^/?]*\\.#", $url)) { |
295
|
|
|
// URLs starting with domain: 'example.com', 'example.com/subpage' |
296
|
2 |
|
return "http://$url"; |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
// 'page/handler', 'mod/plugin/file.php' |
300
|
|
|
// trim off any leading / because the site URL is stored |
301
|
|
|
// with a trailing / |
302
|
210 |
|
return elgg_get_site_url() . ltrim($url, '/'); |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* When given a title, returns a version suitable for inclusion in a URL |
307
|
|
|
* |
308
|
|
|
* @param string $title The title |
309
|
|
|
* |
310
|
|
|
* @return string The optimized title |
311
|
|
|
* @since 1.7.2 |
312
|
|
|
*/ |
313
|
|
|
function elgg_get_friendly_title($title) { |
314
|
|
|
|
315
|
|
|
// return a URL friendly title to short circuit normal title formatting |
316
|
|
|
$params = array('title' => $title); |
317
|
|
|
$result = elgg_trigger_plugin_hook('format', 'friendly:title', $params, null); |
318
|
|
|
if ($result) { |
319
|
|
|
return $result; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
// titles are often stored HTML encoded |
323
|
|
|
$title = html_entity_decode($title, ENT_QUOTES, 'UTF-8'); |
324
|
|
|
|
325
|
|
|
$title = \Elgg\Translit::urlize($title); |
326
|
|
|
|
327
|
|
|
return $title; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* Formats a UNIX timestamp in a friendly way (eg "less than a minute ago") |
332
|
|
|
* |
333
|
|
|
* @see elgg_view_friendly_time() |
334
|
|
|
* |
335
|
|
|
* @param int $time A UNIX epoch timestamp |
336
|
|
|
* @param int $current_time Current UNIX epoch timestamp (optional) |
337
|
|
|
* |
338
|
|
|
* @return string The friendly time string |
339
|
|
|
* @since 1.7.2 |
340
|
|
|
*/ |
341
|
|
|
function elgg_get_friendly_time($time, $current_time = null) { |
342
|
|
|
|
343
|
7 |
|
if (!$current_time) { |
344
|
|
|
$current_time = time(); |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
// return a time string to short circuit normal time formatting |
348
|
7 |
|
$params = array('time' => $time, 'current_time' => $current_time); |
349
|
7 |
|
$result = elgg_trigger_plugin_hook('format', 'friendly:time', $params, null); |
350
|
7 |
|
if ($result) { |
351
|
|
|
return $result; |
352
|
|
|
} |
353
|
|
|
|
354
|
7 |
|
$diff = abs((int)$current_time - (int)$time); |
355
|
|
|
|
356
|
7 |
|
$minute = 60; |
357
|
7 |
|
$hour = $minute * 60; |
358
|
7 |
|
$day = $hour * 24; |
359
|
|
|
|
360
|
7 |
|
if ($diff < $minute) { |
361
|
1 |
|
return elgg_echo("friendlytime:justnow"); |
362
|
|
|
} |
363
|
|
|
|
364
|
6 |
|
if ($diff < $hour) { |
365
|
3 |
|
$granularity = ':minutes'; |
366
|
3 |
|
$diff = round($diff / $minute); |
367
|
6 |
|
} else if ($diff < $day) { |
368
|
1 |
|
$granularity = ':hours'; |
369
|
1 |
|
$diff = round($diff / $hour); |
370
|
1 |
|
} else { |
371
|
2 |
|
$granularity = ':days'; |
372
|
2 |
|
$diff = round($diff / $day); |
373
|
|
|
} |
374
|
|
|
|
375
|
6 |
|
if ($diff == 0) { |
376
|
|
|
$diff = 1; |
377
|
|
|
} |
378
|
|
|
|
379
|
6 |
|
$future = ((int)$current_time - (int)$time < 0) ? ':future' : ''; |
380
|
6 |
|
$singular = ($diff == 1) ? ':singular' : ''; |
381
|
|
|
|
382
|
6 |
|
return elgg_echo("friendlytime{$future}{$granularity}{$singular}", array($diff)); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Returns a human-readable message for PHP's upload error codes |
387
|
|
|
* |
388
|
|
|
* @param int $error_code The code as stored in $_FILES['name']['error'] |
389
|
|
|
* @return string |
390
|
|
|
*/ |
391
|
|
|
function elgg_get_friendly_upload_error($error_code) { |
392
|
|
|
switch ($error_code) { |
393
|
|
|
case UPLOAD_ERR_OK: |
394
|
|
|
return ''; |
395
|
|
|
|
396
|
|
|
case UPLOAD_ERR_INI_SIZE: |
397
|
|
|
$key = 'ini_size'; |
398
|
|
|
break; |
399
|
|
|
|
400
|
|
|
case UPLOAD_ERR_FORM_SIZE: |
401
|
|
|
$key = 'form_size'; |
402
|
|
|
break; |
403
|
|
|
|
404
|
|
|
case UPLOAD_ERR_PARTIAL: |
405
|
|
|
$key = 'partial'; |
406
|
|
|
break; |
407
|
|
|
|
408
|
|
|
case UPLOAD_ERR_NO_FILE: |
409
|
|
|
$key = 'no_file'; |
410
|
|
|
break; |
411
|
|
|
|
412
|
|
|
case UPLOAD_ERR_NO_TMP_DIR: |
413
|
|
|
$key = 'no_tmp_dir'; |
414
|
|
|
break; |
415
|
|
|
|
416
|
|
|
case UPLOAD_ERR_CANT_WRITE: |
417
|
|
|
$key = 'cant_write'; |
418
|
|
|
break; |
419
|
|
|
|
420
|
|
|
case UPLOAD_ERR_EXTENSION: |
421
|
|
|
$key = 'extension'; |
422
|
|
|
break; |
423
|
|
|
|
424
|
|
|
default: |
425
|
|
|
$key = 'unknown'; |
426
|
|
|
break; |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
return elgg_echo("upload:error:$key"); |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
|
433
|
|
|
/** |
434
|
|
|
* Strip tags and offer plugins the chance. |
435
|
|
|
* Plugins register for output:strip_tags plugin hook. |
436
|
|
|
* Original string included in $params['original_string'] |
437
|
|
|
* |
438
|
|
|
* @param string $string Formatted string |
439
|
|
|
* @param string $allowable_tags Optional parameter to specify tags which should not be stripped |
440
|
|
|
* |
441
|
|
|
* @return string String run through strip_tags() and any plugin hooks. |
442
|
|
|
*/ |
443
|
|
|
function elgg_strip_tags($string, $allowable_tags = null) { |
444
|
2 |
|
$params['original_string'] = $string; |
445
|
2 |
|
$params['allowable_tags'] = $allowable_tags; |
446
|
|
|
|
447
|
2 |
|
$string = strip_tags($string, $allowable_tags); |
448
|
2 |
|
$string = elgg_trigger_plugin_hook('format', 'strip_tags', $params, $string); |
449
|
|
|
|
450
|
2 |
|
return $string; |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
/** |
454
|
|
|
* Decode HTML markup into a raw text string |
455
|
|
|
* |
456
|
|
|
* This applies html_entity_decode() to a string while re-entitising HTML |
457
|
|
|
* special char entities to prevent them from being decoded back to their |
458
|
|
|
* unsafe original forms. |
459
|
|
|
* |
460
|
|
|
* This relies on html_entity_decode() not translating entities when |
461
|
|
|
* doing so leaves behind another entity, e.g. &gt; if decoded would |
462
|
|
|
* create > which is another entity itself. This seems to escape the |
463
|
|
|
* usual behaviour where any two paired entities creating a HTML tag are |
464
|
|
|
* usually decoded, i.e. a lone > is not decoded, but <foo> would |
465
|
|
|
* be decoded to <foo> since it creates a full tag. |
466
|
|
|
* |
467
|
|
|
* Note: html_entity_decode() is poorly explained in the manual - which is really |
468
|
|
|
* bad given its potential for misuse on user input already escaped elsewhere. |
469
|
|
|
* Stackoverflow is littered with advice to use this function in the precise |
470
|
|
|
* way that would lead to user input being capable of injecting arbitrary HTML. |
471
|
|
|
* |
472
|
|
|
* @param string $string Encoded HTML |
473
|
|
|
* |
474
|
|
|
* @return string |
475
|
|
|
* |
476
|
|
|
* @author Pádraic Brady |
477
|
|
|
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com) |
478
|
|
|
* @license Released under dual-license GPL2/MIT by explicit permission of Pádraic Brady |
479
|
|
|
*/ |
480
|
|
|
function elgg_html_decode($string) { |
481
|
|
|
$string = str_replace( |
482
|
|
|
array('>', '<', '&', '"', '''), |
483
|
|
|
array('&gt;', '&lt;', '&amp;', '&quot;', '&#039;'), |
484
|
|
|
$string |
485
|
|
|
); |
486
|
|
|
$string = html_entity_decode($string, ENT_NOQUOTES, 'UTF-8'); |
487
|
|
|
$string = str_replace( |
488
|
|
|
array('&gt;', '&lt;', '&amp;', '&quot;', '&#039;'), |
489
|
|
|
array('>', '<', '&', '"', '''), |
490
|
|
|
$string |
491
|
|
|
); |
492
|
|
|
return $string; |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
/** |
496
|
|
|
* Prepares query string for output to prevent CSRF attacks. |
497
|
|
|
* |
498
|
|
|
* @param string $string |
499
|
|
|
* @return string |
500
|
|
|
* |
501
|
|
|
* @access private |
502
|
|
|
*/ |
503
|
|
|
function _elgg_get_display_query($string) { |
504
|
|
|
//encode <,>,&, quotes and characters above 127 |
505
|
|
|
if (function_exists('mb_convert_encoding')) { |
506
|
|
|
$display_query = mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8'); |
507
|
|
|
} else { |
508
|
|
|
// if no mbstring extension, we just strip characters |
509
|
|
|
$display_query = preg_replace("/[^\x01-\x7F]/", "", $string); |
510
|
|
|
} |
511
|
|
|
return htmlspecialchars($display_query, ENT_QUOTES, 'UTF-8', false); |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
/** |
515
|
|
|
* Use a "fixed" filter_var() with FILTER_VALIDATE_URL that handles multi-byte chars. |
516
|
|
|
* |
517
|
|
|
* @param string $url URL to validate |
518
|
|
|
* @return string|false |
519
|
|
|
* @access private |
520
|
|
|
*/ |
521
|
|
|
function _elgg_sane_validate_url($url) { |
522
|
|
|
// based on http://php.net/manual/en/function.filter-var.php#104160 |
523
|
223 |
|
$res = filter_var($url, FILTER_VALIDATE_URL); |
524
|
223 |
|
if ($res) { |
525
|
58 |
|
return $res; |
526
|
|
|
} |
527
|
|
|
|
528
|
|
|
// Check if it has unicode chars. |
529
|
217 |
|
$l = elgg_strlen($url); |
530
|
217 |
|
if (strlen($url) == $l) { |
531
|
217 |
|
return $res; |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
// Replace wide chars by “X”. |
535
|
1 |
|
$s = ''; |
536
|
1 |
|
for ($i = 0; $i < $l; ++$i) { |
537
|
1 |
|
$ch = elgg_substr($url, $i, 1); |
538
|
1 |
|
$s .= (strlen($ch) > 1) ? 'X' : $ch; |
539
|
1 |
|
} |
540
|
|
|
|
541
|
|
|
// Re-check now. |
542
|
1 |
|
return filter_var($s, FILTER_VALIDATE_URL) ? $url : false; |
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) { |
|
|
|
|
546
|
|
|
|
547
|
|
|
}; |
548
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.