Example #1
0
	/**
	 * 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;
	}
Example #2
0
	/**
	 * 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;
	}
Example #3
0
	/**
	 * 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;
	}