Jacek Kowalski
2024-08-17 7c2d04008df30360e5d9a2a53f42d77fa10757ea
commit | author | age
bcd661 1 <?php
JK 2 class Fetch {
3     static function ftp($url, $file = NULL) {
4         $url = parse_url($url);
5         if(!isset($url['scheme']) || $url['scheme'] != 'ftp') {
6             throw new Exception('Only FTP URLs are supported');
7         }
8         if(!isset($url['host'])) {
9             throw new Exception('Hostname not present in the URL');
10         }
11         if(!isset($url['path'])) {
12             throw new Exception('Path component not present in the URL');
13         }
14         if(!isset($url['port'])) {
15             $url['port'] = 21;
16         }
17         if(!isset($url['user'])) {
18             $url['user'] = 'anonymous';
19         }
20         if(!isset($url['pass'])) {
21             $url['pass'] = 'anonymous@mpk.jacekk.net';
22         }
9419f7 23         if($file === NULL) {
bcd661 24             $file = basename($url['path']);
JK 25         }
26         
27         $localTime = -1;
28         $localSize = -1;
29         if(is_file($file)) {
30             $localTime = filemtime($file);
31             $localSize = filesize($file);
32         }
33         
34         $ftp = FtpConnection::create($url['host'], $url['port'], $url['user'], $url['pass']);
35         $remoteSize = $ftp->size($url['path']);
36         $remoteTime = $ftp->mdtm($url['path']);
37         
38         $updated = FALSE;
39         
9419f7 40         if($localTime >= $remoteTime && $localSize == $remoteSize) {
JK 41             return FALSE;
bcd661 42         }
JK 43         
9419f7 44         if(file_exists($file.'.tmp')) {
JK 45             unlink($file.'.tmp');
46         }
47         $ftp->get($file.'.tmp', $url['path'], FTP_BINARY);
48         touch($file.'.tmp', $remoteTime);
49         if(!rename($file.'.tmp', $file)) {
50             throw new Exception('Temporary file rename failed');
51         }
52         
53         return TRUE;
54     }
55     
56     static function parse_http_headers($headers) {
57         $hasHeader = FALSE;
58         foreach($headers as $header) {
59             if(substr($header, 0, 5) === 'HTTP/') {
60                 $code = substr($header, 9, 3);
61                 if($code === '304') {
62                     return NULL;
63                 } elseif(substr($code, 0, 1) == '2') {
64                     $hasHeader = TRUE;
65                 }
66             } elseif($hasHeader && strtolower(substr($header, 0, 15)) === 'last-modified: ') {
67                 return strptime(substr($header, 15), 'D, d M Y H:i:s T');
68             }
69         }
70         return FALSE;
bcd661 71     }
JK 72     
73     static function generic($url, $file = NULL) {
9419f7 74         if($file === NULL) {
bcd661 75             $file = basename($url['url']);
JK 76         }
9419f7 77         
JK 78         $context = [];
79         if(is_file($file)) {
80             $file_date = filemtime($file);
81             $context['http'] = [
82                 'header' => [
83                     'If-Modified-Since: '.gmdate('D, d M Y H:i:s T', $file_date),
84                 ],
7c2d04 85                 'timeout' => 15,
9419f7 86             ];
JK 87         }
88         
89         $data = file_get_contents($url, FALSE, stream_context_create($context));
90         $remoteTime = FALSE;
91         if(isset($http_response_header) && is_array($http_response_header)) {
92             $remoteTime = self::parse_http_headers($http_response_header);
93             if($remoteTime === NULL) {
94                 return FALSE;
95             }
96         }
97         
bcd661 98         if($data === FALSE) {
JK 99             throw new Exception('URL fetch failed');
100         }
101         if(file_put_contents($file.'.tmp', $data) === FALSE) {
102             throw new Exception('Temporary file creation failed');
103         }
9419f7 104         if($remoteTime !== FALSE) {
JK 105             touch($file.'.tmp', $remoteTime);
106         }
bcd661 107         if(!rename($file.'.tmp', $file)) {
JK 108             throw new Exception('Temporary file rename failed');
109         }
9419f7 110         
JK 111         return TRUE;
112     }
113     
114     static function auto($url, $file = NULL) {
115         if($file === NULL) {
116             $file = basename($url['url']);
117         }
118         if(substr($url, 0, 4) == 'ftp:') {
119             return self::ftp($url, $file);
120         }
121         return self::generic($url, $file);
bcd661 122     }
JK 123 }