size($url['path']); $remoteTime = $ftp->mdtm($url['path']); $updated = FALSE; if($localTime >= $remoteTime && $localSize == $remoteSize) { return FALSE; } if(file_exists($file.'.tmp')) { unlink($file.'.tmp'); } $ftp->get($file.'.tmp', $url['path'], FTP_BINARY); touch($file.'.tmp', $remoteTime); if(!rename($file.'.tmp', $file)) { throw new Exception('Temporary file rename failed'); } return TRUE; } static function parse_http_headers($headers) { $hasHeader = FALSE; foreach($headers as $header) { if(substr($header, 0, 5) === 'HTTP/') { $code = substr($header, 9, 3); if($code === '304') { return NULL; } elseif(substr($code, 0, 1) == '2') { $hasHeader = TRUE; } } elseif($hasHeader && strtolower(substr($header, 0, 15)) === 'last-modified: ') { return strptime(substr($header, 15), 'D, d M Y H:i:s T'); } } return FALSE; } static function generic($url, $file = NULL) { if($file === NULL) { $file = basename($url['url']); } $context = []; if(is_file($file)) { $file_date = filemtime($file); $context['http'] = [ 'header' => [ 'If-Modified-Since: '.gmdate('D, d M Y H:i:s T', $file_date), ], 'timeout' => 15, ]; } $data = file_get_contents($url, FALSE, stream_context_create($context)); $remoteTime = FALSE; if(isset($http_response_header) && is_array($http_response_header)) { $remoteTime = self::parse_http_headers($http_response_header); if($remoteTime === NULL) { return FALSE; } } if($data === FALSE) { throw new Exception('URL fetch failed'); } if(file_put_contents($file.'.tmp', $data) === FALSE) { throw new Exception('Temporary file creation failed'); } if($remoteTime !== FALSE) { touch($file.'.tmp', $remoteTime); } if(!rename($file.'.tmp', $file)) { throw new Exception('Temporary file rename failed'); } return TRUE; } static function auto($url, $file = NULL) { if($file === NULL) { $file = basename($url['url']); } if(substr($url, 0, 4) == 'ftp:') { return self::ftp($url, $file); } return self::generic($url, $file); } }