Jacek Kowalski
2023-07-24 8cde7c538ea1d0d8aa51bcb3f2482ae4f19713ad
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                 ],
85             ];
86         }
87         
88         $data = file_get_contents($url, FALSE, stream_context_create($context));
89         $remoteTime = FALSE;
90         if(isset($http_response_header) && is_array($http_response_header)) {
91             $remoteTime = self::parse_http_headers($http_response_header);
92             if($remoteTime === NULL) {
93                 return FALSE;
94             }
95         }
96         
bcd661 97         if($data === FALSE) {
JK 98             throw new Exception('URL fetch failed');
99         }
100         if(file_put_contents($file.'.tmp', $data) === FALSE) {
101             throw new Exception('Temporary file creation failed');
102         }
9419f7 103         if($remoteTime !== FALSE) {
JK 104             touch($file.'.tmp', $remoteTime);
105         }
bcd661 106         if(!rename($file.'.tmp', $file)) {
JK 107             throw new Exception('Temporary file rename failed');
108         }
9419f7 109         
JK 110         return TRUE;
111     }
112     
113     static function auto($url, $file = NULL) {
114         if($file === NULL) {
115             $file = basename($url['url']);
116         }
117         if(substr($url, 0, 4) == 'ftp:') {
118             return self::ftp($url, $file);
119         }
120         return self::generic($url, $file);
bcd661 121     }
JK 122 }