/** * Save this meta file back up to the FTP server. * * @throws \Exception */ public function saveMetas(){ if($this->_contents === null){ // Contents never loaded, nothing to save. return; } if(!$this->_changed){ // File wasn't changed, nothing to save. return; } $remotefile = $this->_dir . '.ftpmetas'; // Make sure the local directory exists and is writable first! // This will effectively touch the file to ensure it's writable and everything. $this->_local->putContents(''); $fh = fopen($this->_local->getFilename(), 'w'); if(!$fh){ throw new \Exception('Unable to open ' . $this->_local->getFilename() . ' for writing.'); } // Write the current header. fputcsv($fh, ['filename', 'hash', 'modified', 'size']); // And each line. foreach($this->_contents as $c){ fputcsv($fh, array_values($c)); } fclose($fh); // And publish to the FTP server. ftp_put($this->_ftp->getConn(), $remotefile, $this->_local->getFilename(), FTP_BINARY); $this->_changed = false; }
/** * Get the temporary local version of the file. * This is useful for doing operations such as hash and identicalto. * * @return FileLocal */ protected function _getTmpLocal() { if ($this->_tmplocal === null) { $f = md5($this->getFilename()); // Gotta love obviously-named flags. $needtodownload = true; $this->_tmplocal = Filestore\Factory::File('tmp/remotefile-cache/' . $f); // File exists already! Check and see if it needs to be redownloaded. if ($this->cacheable && $this->_tmplocal->exists()) { // Lookup this file in the system cache. $systemcachedata = Cache::Get('remotefile-cache-header-' . $f); if ($systemcachedata && isset($systemcachedata['headers'])) { // I can only look them up if the cache is available. // First check will be the expires header. if(isset($systemcachedata['headers']['Expires']) && strtotime($systemcachedata['headers']['Expires']) > time()){ $needtodownload = false; // And set the headers! // This is required $this->_headers = $systemcachedata['headers']; $this->_response = $systemcachedata['response']; } // Next, try ETag. elseif ($this->_getHeader('ETag') && isset($systemcachedata['headers']['ETag'])) { $needtodownload = ($this->_getHeader('ETag') != $systemcachedata['headers']['ETag']); } // No? How 'bout elseif ($this->_getHeader('Last-Modified') && isset($systemcachedata['headers']['Last-Modified'])) { $needtodownload = ($this->_getHeader('Last-Modified') != $systemcachedata['headers']['Last-Modified']); } // Still no? The default is to download it anyway. } } if ($needtodownload || !$this->cacheable) { // Make sure that the headers are updated, this is a requirement to use the 302 tag. $this->_getHeaders(); if(($this->_response == '302' || $this->_response == '301') && $this->_redirectFile !== null){ $this->_tmplocal = $this->_redirectFile->_getTmpLocal(); } else{ // BTW, use cURL. $curl = curl_init(); curl_setopt_array( $curl, array( CURLOPT_HEADER => false, CURLOPT_NOBODY => false, CURLOPT_RETURNTRANSFER => true, CURLOPT_URL => $this->getURL(), CURLOPT_HTTPHEADER => \Core::GetStandardHTTPHeaders(true), ) ); $result = curl_exec($curl); if($result === false){ switch(curl_errno($curl)){ case CURLE_COULDNT_CONNECT: case CURLE_COULDNT_RESOLVE_HOST: case CURLE_COULDNT_RESOLVE_PROXY: $this->_response = 404; return $this->_tmplocal; break; default: $this->_response = 500; return $this->_tmplocal; break; } } curl_close($curl); // Copy the data down to the local file. $this->_tmplocal->putContents($result); } // And remember this header data for nexttime. Cache::Set( 'remotefile-cache-header-' . $f, [ 'headers' => $this->_getHeaders(), 'response' => $this->_response, ] ); } } return $this->_tmplocal; }
/** * Static function to act as Factory for the underlying Filestore system. * This will parse the incoming URI and return the appropriate type based on Core settings and filetype. * * @param $uri * * @return File */ public static function File($uri) { // GOGO caching ;) if(isset(self::$_ResolveCache[$uri])){ $resolved = self::$_ResolveCache[$uri]->getFilename(); if(isset(self::$_Files[$resolved])){ return self::$_Files[$resolved]; } } // self::$_Files[$originaluri] //var_dump($uri); // base64 comes first. If the filename is encoded in that, decode it first. if (strpos($uri, 'base64:') === 0){ $uri = base64_decode(substr($uri, 7)); } // Allow FTP files to be requested here! // This needs to be before the :// check, because technically FTP can be a remote file, // but it has extra functionality, (namely being able to write or perform other operations through FTP) if(strpos($uri, 'ftp://') === 0){ // Don't cache remote files. return new Backends\FileFTP($uri); } if(strpos($uri, ROOT_PDIR) === 0){ // No change needed ;) } elseif(strpos($uri, ROOT_URL_NOSSL) === 0){ // If this is a local file, just the URL version.... allow that remap too! $uri = ROOT_PDIR . substr($uri, strlen(ROOT_URL_NOSSL)); } elseif(strpos($uri, ROOT_URL_SSL) === 0){ // If this is a local file, just the URL version.... allow that remap too! $uri = ROOT_PDIR . substr($uri, strlen(ROOT_URL_SSL)); } // Allow remote files to be requested here too! if(strpos($uri, '://') !== false){ // Don't cache remote files. return new Backends\FileRemote($uri); } if( strpos($uri, 'asset/') === 0 || strpos($uri, 'assets/') === 0 || strpos($uri, get_asset_path()) === 0 ){ // Is this an asset request? $file = resolve_asset_file($uri); } elseif( strpos($uri, 'public/') === 0 || strpos($uri, get_public_path()) === 0 ){ // Is this a public request? $file = resolve_public_file($uri); } elseif( strpos($uri, 'private/') === 0 || strpos($uri, get_private_path()) === 0 ){ // Is this a private request? $file = resolve_private_file($uri); } elseif( strpos($uri, 'tmp/') === 0 ){ // Is this a tmp request? $file = new Backends\FileLocal(get_tmp_path() . substr($uri, 4)); } elseif( strpos($uri, get_tmp_path()) === 0 || strpos($uri, '/tmp/') === 0 ){ // tmp fully resolved? $file = new Backends\FileLocal($uri); } elseif(\Core\ftp() && EXEC_MODE == 'WEB'){ // Umm.... ok // Still, try to use the FTP proxy files if it's enabled. $file = new Backends\FileFTP($uri); } else{ // Screw it... regular file it is! $file = new Backends\FileLocal($uri); } // Cache this for future calls on this page load. self::$_Files[$file->getFilename()] = $file; return $file; }