summaryrefslogtreecommitdiff
path: root/library/WT/File.php
blob: 5c0f254818c8727449eadbe72bd83c1a727082e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php
// File manipulation utilities
//
// webtrees: Web based Family History software
// Copyright (c) 2014 webtrees development team
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

class WT_File {
	//////////////////////////////////////////////////////////////////////////////
	// Fetch a remote file
	// Note that fopen() and file_get_contents() are often unvailable, as they
	// can easily be exploited by application bugs, and are therefore disabled.
	// Hence we use fsockopen().
	// To allow arbitrarily large downloads with small memory limits, we either
	// write output to a stream or return it.
	//////////////////////////////////////////////////////////////////////////////

	public static function fetchUrl($url, $stream=null) {
		$host  = parse_url($url, PHP_URL_HOST);
		$port  = parse_url($url, PHP_URL_PORT);
		$path  = parse_url($url, PHP_URL_PATH);
		$query = parse_url($url, PHP_URL_QUERY);

		if (!$port) {
			$port = parse_url($url, PHP_URL_SCHEME) == 'https' ? 443 : 80;
		}

		$scheme = $port == 443 ? 'ssl://' : '';

		$fp = @fsockopen($scheme . $host, $port, $errno, $errstr, 5);
		if (!$fp) {
			return null;
		}

		fputs($fp, "GET $path?$query HTTP/1.0\r\nHost: $host\r\nConnection: Close\r\n\r\n");

		// The first part of the response include the HTTP headers
		$response = fread($fp, 65536);

		// The file has moved?  Follow it.
		if (preg_match('/^HTTP\/1.[01] 30[23].+\nLocation: ([^\r\n]+)/s', $response, $match)) {
			fclose($fp);
			return WT_File::fetchUrl($match[1], $stream);
		} else {
			// The response includes headers, a blank line, then the content
			$response = substr($response, strpos($response, "\r\n\r\n") + 4);
		}

		if ($stream) {
			fwrite($stream, $response);
			while ($tmp = fread($fp, 8192)) {
				fwrite($stream, $tmp);
			}
			fclose($fp);
			return null;
		} else  {
			while ($tmp = fread($fp, 8192)) {
				$response .= $tmp;
			}
			fclose($fp);
			return $response;
		}
	}

	//////////////////////////////////////////////////////////////////////////////
	// Recursively delete a folder or file
	//////////////////////////////////////////////////////////////////////////////

	public static function delete($path) {
		// In case the file is marked read-only
		@chmod($path, 0777);

		if (is_dir($path)) {
			$dir = opendir($path);
			while ($dir !== false && (($file = readdir($dir)) !== false)) {
				if ($file != '.' && $file != '..') {
					WT_File::delete($path . DIRECTORY_SEPARATOR . $file);
				}
			}
			closedir($dir);
			@rmdir($path);
		} else {
			@unlink($path);
		}
		return !file_exists($path);
	}

	//////////////////////////////////////////////////////////////////////////////
	// Create a folder, and subfolders, if it does not already exist
	//////////////////////////////////////////////////////////////////////////////

	public static function mkdir($path) {
		if (!is_dir($path)) {
			if (!is_dir(dirname($path))) {
				WT_File::mkdir(dirname($path));
			}
			@mkdir($path);
			return is_dir($path);
		} else {
			return true;
		}
	}
}