Completed
Pull Request — master (#105)
by
unknown
01:38
created

Utils.php ➔ copy_dir()   B

Complexity

Conditions 9
Paths 7

Size

Total Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 7
nop 2
dl 0
loc 36
rs 8.0555
c 0
b 0
f 0
1
<?php
2
/**
3
 * @name      OpenImporter
4
 * @copyright OpenImporter contributors
5
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
6
 *
7
 * @version 1.0 Alpha
8
 *
9
 * This file contains code based on:
10
 *
11
 * Simple Machines Forum (SMF)
12
 * copyright:    2011 Simple Machines (http://www.simplemachines.org)
13
 * license:    BSD, See included LICENSE.TXT for terms and conditions.
14
 */
15
16
/**
17
 * Checks if we've passed a time limit..
18
 *
19
 * @param int|null $substep
20
 * @param int $stop_time
21
 *
22
 * @return null
23
 */
24
function pastTime($substep = null, $stop_time = 5)
25
{
26
	global $oi_import, $time_start;
27
28
	if (isset($_GET['substep']) && $_GET['substep'] < $substep)
29
	{
30
		$_GET['substep'] = $substep;
31
	}
32
33
	// Some details for our progress bar
34
	if (isset($oi_import->count->$substep) && $oi_import->count->$substep > 0 && isset($_REQUEST['start']) && $_REQUEST['start'] > 0 && isset($substep))
35
	{
36
		$bar = round($_REQUEST['start'] / $oi_import->count->$substep * 100, 0);
37
	}
38
	else
39
	{
40
		$bar = false;
41
	}
42
43
	@set_time_limit(300);
44
	if (is_callable('apache_reset_timeout'))
45
	{
46
		apache_reset_timeout();
47
	}
48
49
	if (time() - $time_start < $stop_time)
50
	{
51
		return;
52
	}
53
54
	// @todo maybe throw an exception?
55
	$oi_import->template->time_limit($bar, $_SESSION['import_progress'], $_SESSION['import_overall']);
56
	$oi_import->template->footer();
57
58
	exit;
59
}
60
61
/**
62
 * Helper function, simple file copy at all
63
 *
64
 * @param string $source
65
 * @param string $destination
66
 *
67
 * @return boolean
68
 */
69
function copy_file($source, $destination)
70
{
71
	create_folders_recursive(dirname($destination));
72
73
	if (is_file($source))
74
	{
75
		copy($source, $destination);
76
77
		return false;
78
	}
79
80
	return true;
81
}
82
83
function copy_dir_recursive($source, $destination)
84
{
85
	// Create the destination tree
86
	$destination = rtrim($destination, '\\/') . DIRECTORY_SEPARATOR;
87
	create_folders_recursive($destination);
88
89
	$source = rtrim($source, '\\/') . DIRECTORY_SEPARATOR;
90
	$dir = opendir($source);
91
92
	// If we can't open the directory ...
93
	if ($dir === false)
94
	{
95
		return;
96
	}
97
98
	while ($file = readdir($dir))
99
	{
100
		if ($file == '.' || $file == '..')
101
		{
102
			continue;
103
		}
104
105
		if (is_dir($source . $file))
106
		{
107
			copy_dir_recursive($source . $file, $destination . $file);
108
		}
109
		else
110
		{
111
			copy($source . $file, $destination . $file);
112
		}
113
	}
114
}
115
116
/**
117
 * Create attachment folders as deep as needed.
118
 *
119
 * @param $path
120
 */
121
function create_folders_recursive($path)
122
{
123
	$parent = dirname($path);
124
125
	if (!file_exists($parent))
126
	{
127
		create_folders_recursive($parent);
128
	}
129
130
	if (!file_exists($path))
131
	{
132
		@mkdir($path, 0755);
133
	}
134
}
135
136
/**
137
 * Add slashes recursively...
138
 *
139
 * @param array $var
140
 *
141
 * @return array
142
 */
143
function addslashes_recursive($var)
144
{
145
	if (!is_array($var))
146
	{
147
		return addslashes($var);
148
	}
149
	else
150
	{
151
		foreach ($var as $k => $v)
152
		{
153
			$var[$k] = addslashes_recursive($v);
154
		}
155
156
		return $var;
157
	}
158
}
159
160
/**
161
 * Remove slashes recursively...
162
 *
163
 * @param array $var
164
 *
165
 * @return array
166
 */
167
function stripslashes_recursive($var, $level = 0)
168
{
169
	if (!is_array($var))
170
	{
171
		return stripslashes($var);
172
	}
173
174
	// Reindex the array without slashes, this time.
175
	$new_var = array();
176
177
	// Strip the slashes from every element.
178
	foreach ($var as $k => $v)
179
	{
180
		$new_var[stripslashes($k)] = $level > 25 ? null : stripslashes_recursive($v, $level + 1);
181
	}
182
183
	return $new_var;
184
}
185
186
/**
187
 * Copies a directory
188
 *
189
 * @param string $source
190
 * @param string $destination
191
 *
192
 * @return null
193
 */
194
function copy_dir($source, $destination)
195
{
196
	if (!is_dir($source) || !($dir = opendir($source)))
197
	{
198
		return;
199
	}
200
201
	while ($file = readdir($dir))
202
	{
203
		if ($file == '.' || $file == '..')
204
		{
205
			continue;
206
		}
207
208
		// If we have a directory create it on the destination and copy contents into it!
209
		if (is_dir($source . DIRECTORY_SEPARATOR . $file))
210
		{
211
			if (!is_dir($destination))
212
			{
213
				@mkdir($destination, 0755);
214
			}
215
216
			copy_dir($source . DIRECTORY_SEPARATOR . $file, $destination . DIRECTORY_SEPARATOR . $file);
217
		}
218
		else
219
		{
220
			if (!is_dir($destination))
221
			{
222
				@mkdir($destination, 0755);
223
			}
224
225
			copy($source . DIRECTORY_SEPARATOR . $file, $destination . DIRECTORY_SEPARATOR . $file);
226
		}
227
	}
228
	closedir($dir);
229
}
230
231
/**
232
 * Detects, if a string is utf-8 or not
233
 *
234
 * @param string $string
235
 *
236
 * @return boolean
237
 */
238
function is_utf8($string)
239
{
240
	return utf8_encode(utf8_decode($string)) == $string;
241
}
242
243
/**
244
 * Function fix based on ForceUTF8 by Sebastián Grignoli <[email protected]>
245
 * @link http://www.framework2.com.ar/dzone/forceUTF8-es/
246
 * This function leaves UTF8 characters alone, while converting almost all non-UTF8 to UTF8.
247
 *
248
 * It may fail to convert characters to unicode if they fall into one of these scenarios:
249
 *
250
 * 1) when any of these characters:   ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞß
251
 *    are followed by any of these:  ("group B")
252
 *                                    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶•¸¹º»¼½¾¿
253
 * For example:   %ABREPR%C9SENT%C9%BB. «REPRÉSENTÉ»
254
 * The "«" (%AB) character will be converted, but the "É" followed by "»" (%C9%BB)
255
 * is also a valid unicode character, and will be left unchanged.
256
 *
257
 * 2) when any of these: àáâãäåæçèéêëìíîï  are followed by TWO chars from group B,
258
 * 3) when any of these: ðñòó  are followed by THREE chars from group B.
259
 *
260
 * @name fix
261
 *
262
 * @param string|string[] $text Any string.
263
 *
264
 * @return string  The same string, UTF8 encoded
265
 */
266
function fix_charset($text)
267
{
268
	if (is_array($text))
269
	{
270
		foreach ($text as $k => $v)
271
		{
272
			$text[$k] = fix_charset($v);
273
		}
274
275
		return $text;
276
	}
277
	// numeric? There's nothing to do, we simply return our input.
278
	if (is_numeric($text))
279
	{
280
		return $text;
281
	}
282
283
	$max = strlen($text);
284
	$buf = '';
285
286
	for ($i = 0; $i < $max; $i++)
287
	{
288
		$c1 = $text{$i};
289
		if ($c1 >= "\xc0")
290
		{
291
			// Should be converted to UTF8, if it's not UTF8 already
292
			$c2 = $i + 1 >= $max ? "\x00" : $text{$i + 1};
293
			$c3 = $i + 2 >= $max ? "\x00" : $text{$i + 2};
294
			$c4 = $i + 3 >= $max ? "\x00" : $text{$i + 3};
295
			if ($c1 >= "\xc0" & $c1 <= "\xdf")
296
			{
297
				// looks like 2 bytes UTF8
298
				if ($c2 >= "\x80" && $c2 <= "\xbf")
299
				{
300
					// yeah, almost sure it's UTF8 already
301
					$buf .= $c1 . $c2;
302
					$i++;
303
				}
304
				else
305
				{
306
					// not valid UTF8. Convert it.
307
					$cc1 = (chr(ord($c1) / 64) | "\xc0");
308
					$cc2 = ($c1 & "\x3f") | "\x80";
309
					$buf .= $cc1 . $cc2;
310
				}
311
			}
312
			elseif ($c1 >= "\xe0" & $c1 <= "\xef")
313
			{
314
				// looks like 3 bytes UTF8
315
				if ($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf")
316
				{
317
					// yeah, almost sure it's UTF8 already
318
					$buf .= $c1 . $c2 . $c3;
319
					$i = $i + 2;
320
				}
321
				else
322
				{
323
					// not valid UTF8. Convert it.
324
					$cc1 = (chr(ord($c1) / 64) | "\xc0");
325
					$cc2 = ($c1 & "\x3f") | "\x80";
326
					$buf .= $cc1 . $cc2;
327
				}
328
			}
329
			elseif ($c1 >= "\xf0" & $c1 <= "\xf7")
330
			{
331
				// Looks like 4-byte UTF8
332
				if ($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf")
333
				{
334
					// Yeah, almost sure it's UTF8 already
335
					$buf .= $c1 . $c2 . $c3;
336
					$i = $i + 2;
337
				}
338
				else
339
				{
340
					// Not valid UTF8. Convert it.
341
					$cc1 = (chr(ord($c1) / 64) | "\xc0");
342
					$cc2 = ($c1 & "\x3f") | "\x80";
343
					$buf .= $cc1 . $cc2;
344
				}
345
			}
346
			else
347
			{
348
				// Doesn't look like UTF8, but should be converted
349
				$cc1 = (chr(ord($c1) / 64) | "\xc0");
350
				$cc2 = (($c1 & "\x3f") | "\x80");
351
				$buf .= $cc1 . $cc2;
352
			}
353
		}
354
		elseif (($c1 & "\xc0") == "\x80")
355
		{
356
			// Needs conversion
357
			$cc1 = (chr(ord($c1) / 64) | "\xc0");
358
			$cc2 = (($c1 & "\x3f") | "\x80");
359
			$buf .= $cc1 . $cc2;
360
		}
361
		else
362
			// Doesn't need conversion
363
		{
364
			$buf .= $c1;
365
		}
366
	}
367
368
	if (function_exists('mb_decode_numericentity'))
369
	{
370
		$buf = mb_decode_numericentity($buf, array(0x80, 0x2ffff, 0, 0xffff), 'UTF-8');
371
	}
372
	else
373
	{
374
		preg_replace_callback('~(&#(\d{1,7}|x[0-9a-fA-F]{1,6});)~', 'replaceEntities__callback', $buf);
375
	}
376
377
	// surprise, surprise... the string
378
	return $buf;
379
}
380
381
/**
382
 * Decode numeric html entities to their UTF8 equivalent character.
383
 *
384
 * What it does:
385
 * - Callback function for preg_replace_callback in subs-members
386
 * - Uses capture group 2 in the supplied array
387
 * - Does basic scan to ensure characters are inside a valid range
388
 *
389
 * @param mixed[] $matches matches from a preg_match_all
390
 *
391
 * @return string $string
392
 */
393
function replaceEntities__callback($matches)
394
{
395
	if (!isset($matches[2]))
396
	{
397
		return '';
398
	}
399
400
	$num = $matches[2][0] === 'x' ? hexdec(substr($matches[2], 1)) : (int) $matches[2];
401
402
	// Remove left to right / right to left overrides
403
	if ($num === 0x202D || $num === 0x202E)
404
	{
405
		return '';
406
	}
407
408
	// Quote, Ampersand, Apostrophe, Less/Greater Than get html replaced
409
	if (in_array($num, array(0x22, 0x26, 0x27, 0x3C, 0x3E)))
410
	{
411
		return '&#' . $num . ';';
412
	}
413
414
	// <0x20 are control characters, 0x20 is a space, > 0x10FFFF is past the end of the utf8 character set
415
	// 0xD800 >= $num <= 0xDFFF are surrogate markers (not valid for utf8 text)
416
	if ($num < 0x20 || $num > 0x10FFFF || ($num >= 0xD800 && $num <= 0xDFFF))
417
	{
418
		return '';
419
	}
420
	// <0x80 (or less than 128) are standard ascii characters a-z A-Z 0-9 and puncuation
421
	elseif ($num < 0x80)
422
	{
423
		return chr($num);
424
	}
425
	// <0x800 (2048)
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
426
	elseif ($num < 0x800)
427
	{
428
		return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
429
	}
430
	// < 0x10000 (65536)
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
431
	elseif ($num < 0x10000)
432
	{
433
		return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
434
	}
435
	// <= 0x10FFFF (1114111)
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
436
	else
437
	{
438
		return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
439
	}
440
}
441
442
/**
443
 * Helper function for storing vars that need to be global
444
 *
445
 * @param string $variable
446
 * @param string $value
447
 */
448
function store_global($variable, $value)
449
{
450
	$_SESSION['store_globals'][$variable] = $value;
451
}
452
453
/**
454
 * Output some debug information
455
 *
456
 * @param $val
457
 */
458
function print_dbg($val)
459
{
460
	echo '<pre>';
461
	print_r($val);
462
	echo '</pre>';
463
}
464
465
/**
466
 * Helper function to create an encrypted attachment name
467
 *
468
 * @param string $filename
469
 * @return string
470
 */
471
function createAttachmentFilehash($filename)
472
{
473
	return sha1(md5($filename . time()) . mt_rand());
474
}
475
476
/**
477
 * Used to copy smileys from a source to destination.
478
 *
479
 * @param string $source
480
 * @param string $dest
481
 *
482
 * @return type
483
 */
484
function copy_smileys($source, $dest)
485
{
486
	copy_dir($source, $dest);
487
}
488
489
/**
490
 * Return the attachment extension and mime type
491
 *
492
 * @param string $filename
493
 *
494
 * @return array
495
 */
496
function attachment_type($filename)
497
{
498
	// Is this an image (basic ext sniff)
499
	$path_parts = pathinfo($filename);
500
	$ext = $path_parts['extension'];
501
	$basename = $path_parts['filename'];
502
503
	if (!in_array(strtolower($ext), array('jpg', 'jpeg', 'gif', 'png')))
504
	{
505
		$ext = '';
506
		$mime_type = '';
507
	}
508
	else
509
	{
510
		if (strtolower($ext) === 'jpg')
511
		{
512
			$mime_type = 'image/jpeg';
513
		}
514
		else
515
		{
516
			$mime_type = 'image/' . strtolower($ext);
517
		}
518
	}
519
520
	return array($ext, $basename, $mime_type);
521
}