Esempio n. 1
0
	/**
	 * Make a copy of a source Filestore\File into this File.
	 *
	 * (Generally only useful internally)
	 *
	 * @param Filestore\File $src Source file backend
	 * @param bool           $overwrite true to overwrite existing file
	 *
	 * @throws \Exception
	 * @return bool True or False if succeeded.
	 */
	public function copyFrom(Filestore\File $src, $overwrite = false) {
		// Don't overwrite existing files unless told otherwise...
		if (!$overwrite) {
			$c    = 0;
			$ext  = $this->getExtension();
			$base = $this->getBaseFilename(true);
			$dir  = dirname($this->_filename);
			$prefix = $dir . '/' . $base;
			$suffix = (($ext == '') ? '' : '.' . $ext);
			$thathash = $src->getHash();

			$f = $prefix . $suffix;
			while(file_exists($f) && md5_file($f) != $thathash){
				$f = $prefix . '-' . ++$c . '' . $suffix;
			}

			$this->_filename = $f;
		}

		// And do the actual copy!
		// To save memory, try to use as low-level functions as possible.
		$localfilename = $src->getLocalFilename();
		// I also want to know when this file was modified so I can set the new version to have the same datestamp.
		$modifiedtime = $src->getMTime();

		$ftp    = \Core\ftp();
		$tmpdir = TMP_DIR;
		if ($tmpdir{0} != '/') $tmpdir = ROOT_PDIR . $tmpdir; // Needs to be fully resolved

		// Resolve it from its default.
		// This is provided from a config define, (probably).
		$mode = (defined('DEFAULT_FILE_PERMS') ? DEFAULT_FILE_PERMS : 0644);

		// Make sure the directory exists first!
		// This has to be done regardless of FTP mode or not.
		self::_Mkdir(dirname($this->_filename), null, true);

		if (
			!$ftp || // FTP not enabled or
			(strpos($this->_filename, $tmpdir) === 0) // Destination is a temporary file.
		) {
			// Read in only so much data at a time.  This is to prevent
			// PHP from trying to read a full 2GB file into memory at once :S
			$maxbuffer = (1024 * 1024 * 10);
			$handlein  = fopen($localfilename, 'r');
			$handleout = fopen($this->_filename, 'w');

			// Couldn't get a lock on both input and output files.
			if(!$handlein){
				throw new \Exception('Unable to open file ' . $localfilename . ' for reading.');
			}
			if(!$handleout){
				throw new \Exception('Unable to open file ' . $this->_filename . ' for writing.');
			}

			while(!feof($handlein)){
				fwrite($handleout, fread($handlein, $maxbuffer));
			}

			// yayz
			fclose($handlein);
			fclose($handleout);
			chmod($this->_filename, $mode);
			// Don't forget the mtime ;)
			touch($this->_filename, $modifiedtime);
			return true;
		}
		else {
			// Trim off the ROOT_PDIR since it'll be relative to the ftp root set in the config.
			if (strpos($this->_filename, ROOT_PDIR) === 0){
				$filename = substr($this->_filename, strlen(ROOT_PDIR));
			}
			else{
				$filename = $this->_filename;
			}

			// Re-acquire the FTP connection.  Core will reset the cwd back to root upon doing this.
			// This is required because mkdir may change directories.
			$ftp = \Core\ftp();
			// FTP requires a filename, not data...
			// WELL how bout that!  I happen to have a local filename ;)
			if (!ftp_put($ftp, $filename, $localfilename, FTP_BINARY)) {
				throw new \Exception(error_get_last()['message']);
			}

			if (!ftp_chmod($ftp, $mode, $filename)){
				throw new \Exception(error_get_last()['message']);
			}

			// woot...
			return true;
		}
	}
Esempio n. 2
0
	/**
	 * Make a copy of a source Filestore\File into this Filestore\File.
	 *
	 * (Generally only useful internally)
	 *
	 * @param Filestore\File $src       Source file backend
	 * @param bool $overwrite true to overwrite existing file
	 *
	 * @throws \Exception
	 * @return bool True or False if succeeded.
	 */
	public function copyFrom(Filestore\File $src, $overwrite = false) {
		// Don't overwrite existing files unless told otherwise...
		if (!$overwrite) {
			$c    = 0;
			$ext  = $this->getExtension();
			$base = $this->getBaseFilename(true);
			$dir  = dirname($this->_filename);
			$prefix = $dir . '/' . $base;
			$suffix = (($ext == '') ? '' : '.' . $ext);
			$thathash = $src->getHash();

			$f = $prefix . $suffix;
			while(file_exists($f) && md5_file($f) != $thathash){
				$f = $prefix . ' (' . ++$c . ')' . $suffix;
			}

			$this->_filename = $f;
		}

		// And do the actual copy!
		// To save memory, try to use as low-level functions as possible.
		$localfilename = $src->getLocalFilename();
		$localhash     = $src->getHash();
		$localmodified = $src->getMTime();
		$localsize     = $src->getFilesize();

		// Resolve it from its default.
		// This is provided from a config define, (probably).
		$mode = (defined('DEFAULT_FILE_PERMS') ? DEFAULT_FILE_PERMS : 0644);

		// Make sure the directory exists first!
		$this->_mkdir(dirname($this->_filename), null, true);

		// FTP requires a filename, not data...
		// WELL how bout that!  I happen to have a local filename ;)
		if (!ftp_put($this->_ftp->getConn(), $this->_filename, $localfilename, FTP_BINARY)) {
			throw new \Exception(error_get_last()['message']);
		}

		if (!ftp_chmod($this->_ftp->getConn(), $mode, $this->_filename)){
			throw new \Exception(error_get_last()['message']);
		}

		// Don't forget to save the metadata for this file!
		$filename = $this->getFilename();
		$this->_ftp->setFileHash($filename, $localhash);
		$this->_ftp->setFileModified($filename, $localmodified);
		$this->_ftp->setFileSize($filename, $localsize);

		// woot...
		return true;
	}
Esempio n. 3
0
/**
 * Get an array of the various resize components from a given dimension set.
 * These include: width, height, mode, key.
 *
 * @param string|int $dimensions
 * @param File $file
 *
 * @return array
 */
function get_resized_key_components($dimensions, $file){
	// The legacy support for simply a number.
	if (is_numeric($dimensions)) {
		$width  = $dimensions;
		$height = $dimensions;
		$mode = '';
	}
	elseif ($dimensions === null) {
		$width  = 300;
		$height = 300;
		$mode = '';
	}
	elseif($dimensions === false){
		$width = false;
		$height = false;
		$mode = '';
	}
	else {
		// Allow some special modifiers.
		if(strpos($dimensions, '^') !== false){
			// Fit the smallest dimension instead of the largest, (useful for overflow tricks)
			$mode = '^';
			$dimensions = str_replace('^', '', $dimensions);
		}
		elseif(strpos($dimensions, '!') !== false){
			// Absolutely resize, regardless of aspect ratio
			$mode = '!';
			$dimensions = str_replace('!', '', $dimensions);
		}
		elseif(strpos($dimensions, '>') !== false){
			// Only increase images.
			$mode = '>';
			$dimensions = str_replace('>', '', $dimensions);
		}
		elseif(strpos($dimensions, '<') !== false){
			// Only decrease images.
			$mode = '<';
			$dimensions = str_replace('<', '', $dimensions);
		}
		else{
			// Default mode
			$mode = '';
		}
		// New method. Split on the "x" and that should give me the width/height.
		$vals   = explode('x', strtolower($dimensions));
		$width  = (int)$vals[0];
		$height = (int)$vals[1];
	}

	$ext = $file->getExtension();
	// Ensure that an extension is used if none present, (may happen with temporary files).
	if(!$ext){
		$ext = mimetype_to_extension($file->getMimetype());
	}

	// The basename is for SEO purposes, that way even resized images still contain the filename.
	// The hash is just to ensure that no two files conflict, ie: /public/a/file1.png and /public/b/file1.png
	//  might conflict without this hash.
	// Finally, the width and height dimensions are there just because as well; it gives more of a human
	//  touch to the file. :p
	// Also, keep the original file extension, this way PNGs remain PNGs, GIFs remain GIFs, JPEGs remain JPEGs.
	// This is critical particularly when it comes to animated GIFs.
	$key = str_replace(' ', '-', $file->getBasename(true)) . '-' . $file->getHash() . '-' . $width . 'x' . $height . $mode . '.' . $ext;

	// The directory can be used with the new File backend to create this file in a correctly nested subdirectory.
	$dir = dirname($file->getFilename(false)) . '/';

	if(substr($dir, 0, 7) == 'public/'){
		// Replace the necessary prefix with a more useful one.
		// Anything within public/ needs to be remapped to public/tmp
		$dir = 'public/tmp/' . substr($dir, 7);
	}
	else{
		// Everything else gets prepended to public/tmp/
		// so if the original file is in themes/blah/imgs/blah.jpg,
		// it will be copied to public/tmp/blah.jpg
		$dir = 'public/tmp/';
	}

	return array(
		'width'  => $width,
		'height' => $height,
		'mode'   => $mode,
		'key'    => $key,
		'ext'    => $ext,
		'dir'    => $dir,
	);
}