mirror of
https://github.com/mosbth/cimage.git
synced 2025-07-31 13:40:08 +02:00
remote download #43
This commit is contained in:
231
CHttpGet.php
231
CHttpGet.php
@@ -5,20 +5,20 @@
|
||||
*/
|
||||
class CHttpGet
|
||||
{
|
||||
private $request = [];
|
||||
private $response = [];
|
||||
|
||||
|
||||
|
||||
private $request = array();
|
||||
private $response = array();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->request['header'] = [];
|
||||
}
|
||||
|
||||
$this->request['header'] = array();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -30,9 +30,25 @@ class CHttpGet
|
||||
*/
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->request['url'] = urlencode($url);
|
||||
$this->request['url'] = $url;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set custom header field for the request.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeader($field, $value)
|
||||
{
|
||||
$this->request['header'][] = "$field: $value";
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -44,58 +60,181 @@ class CHttpGet
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeader($field, $value)
|
||||
public function parseHeader()
|
||||
{
|
||||
$this->request['header']['field'] = $value;
|
||||
$header = explode("\r\n", rtrim($this->response['headerRaw'], "\r\n"));
|
||||
$output = array();
|
||||
|
||||
if ('HTTP' === substr($header[0], 0, 4)) {
|
||||
list($output['version'], $output['status']) = explode(' ', $header[0]);
|
||||
unset($header[0]);
|
||||
}
|
||||
|
||||
foreach ($header as $entry) {
|
||||
$pos = strpos($entry, ':');
|
||||
$output[trim(substr($entry, 0, $pos))] = trim(substr($entry, $pos + 1));
|
||||
}
|
||||
|
||||
$this->response['header'] = $output;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Perform the request.
|
||||
*
|
||||
* @param boolean $debug set to true to dump headers.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function get()
|
||||
public function doGet($debug = false)
|
||||
{
|
||||
$status;
|
||||
$options = array(
|
||||
CURLOPT_URL => $this->request['url'],
|
||||
CURLOPT_HEADER => 1,
|
||||
CURLOPT_HTTPHEADER => $this->request['header'],
|
||||
CURLOPT_AUTOREFERER => true,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLINFO_HEADER_OUT => $debug,
|
||||
CURLOPT_CONNECTTIMEOUT => 5,
|
||||
CURLOPT_TIMEOUT => 5,
|
||||
);
|
||||
|
||||
$options = [
|
||||
CURLOPT_URL => $this->request['url'],
|
||||
CURLOPT_HEADER => 1,
|
||||
CURLOPT_AUTOREFERER => true,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
];
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch, $options);
|
||||
|
||||
//curl_setopt($ch, CURLOPT_URL, $this->request['url']);
|
||||
//curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
|
||||
//curl_setopt($ch, CURLOPT_VERBOSE, 1);
|
||||
//curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)');
|
||||
//curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
//curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
|
||||
//curl_setopt($ch, CURLOPT_TIMEOUT, 5);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
if (!$response) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
$this->response['headerRaw'] = substr($response, 0, $headerSize);
|
||||
$this->response['body'] = substr($response, $headerSize);
|
||||
|
||||
$this->parseHeader();
|
||||
|
||||
if ($debug) {
|
||||
$info = curl_getinfo($ch);
|
||||
echo "Request header<br><pre>", var_dump($info['request_header']), "</pre>";
|
||||
echo "Response header (raw)<br><pre>", var_dump($this->response['headerRaw']), "</pre>";
|
||||
echo "Response header (parsed)<br><pre>", var_dump($this->response['header']), "</pre>";
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
$header = substr($response, 0, $header_size);
|
||||
$body = substr($response, $header_size);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HTTP code of response.
|
||||
*
|
||||
* @return integer as HTTP status code or null if not available.
|
||||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
return isset($this->response['header']['status'])
|
||||
? (int) $this->response['header']['status']
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get file modification time of response.
|
||||
*
|
||||
* @return int as timestamp.
|
||||
*/
|
||||
public function getLastModified()
|
||||
{
|
||||
return isset($this->response['header']['Last-Modified'])
|
||||
? strtotime($this->response['header']['Last-Modified'])
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get content type.
|
||||
*
|
||||
* @return string as the content type or null if not existing or invalid.
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
$type = isset($this->response['header']['Content-Type'])
|
||||
? $this->response['header']['Content-Type']
|
||||
: null;
|
||||
|
||||
return preg_match('#[a-z]+/[a-z]+#', $type)
|
||||
? $type
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get file modification time of response.
|
||||
*
|
||||
* @param mixed $default as default value (int seconds) if date is
|
||||
* missing in response header.
|
||||
*
|
||||
* @return int as timestamp or $default if Date is missing in
|
||||
* response header.
|
||||
*/
|
||||
public function getDate($default = false)
|
||||
{
|
||||
return isset($this->response['header']['Date'])
|
||||
? strtotime($this->response['header']['Date'])
|
||||
: $default;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get max age of cachable item.
|
||||
*
|
||||
* @param mixed $default as default value if date is missing in response
|
||||
* header.
|
||||
*
|
||||
* @return int as timestamp or false if not available.
|
||||
*/
|
||||
public function getMaxAge($default = false)
|
||||
{
|
||||
$cacheControl = isset($this->response['header']['Cache-Control'])
|
||||
? $this->response['header']['Cache-Control']
|
||||
: null;
|
||||
|
||||
$maxAge = null;
|
||||
if ($cacheControl) {
|
||||
// max-age=2592000
|
||||
$part = explode('=', $cacheControl);
|
||||
$maxAge = ($part[0] == "max-age")
|
||||
? (int) $part[1]
|
||||
: null;
|
||||
}
|
||||
|
||||
if ($maxAge) {
|
||||
return $maxAge;
|
||||
}
|
||||
|
||||
$expire = isset($this->response['header']['Expires'])
|
||||
? strtotime($this->response['header']['Expires'])
|
||||
: null;
|
||||
|
||||
return $expire ? $expire : $default;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get body of response.
|
||||
*
|
||||
* @return string as body.
|
||||
*/
|
||||
public function getBody()
|
||||
{
|
||||
return $this->response['body'];
|
||||
}
|
||||
}
|
||||
|
345
CImage.php
345
CImage.php
@@ -17,7 +17,7 @@ class CImage
|
||||
const PNG_RGB_PALETTE = 3;
|
||||
const PNG_GREYSCALE_ALPHA = 4;
|
||||
const PNG_RGB_ALPHA = 6;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -224,7 +224,7 @@ class CImage
|
||||
private $newHeight;
|
||||
private $newHeightOrig; // Save original value
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change target height & width when different dpr, dpr 2 means double image dimensions.
|
||||
*/
|
||||
@@ -250,13 +250,13 @@ class CImage
|
||||
* String with details on how to do image convolution. String
|
||||
* should map a key in the $convolvs array or be a string of
|
||||
* 11 float values separated by comma. The first nine builds
|
||||
* up the matrix, then divisor and last offset.
|
||||
* up the matrix, then divisor and last offset.
|
||||
*/
|
||||
private $convolve;
|
||||
|
||||
|
||||
/**
|
||||
* Custom convolution expressions, matrix 3x3, divisor and offset.
|
||||
* Custom convolution expressions, matrix 3x3, divisor and offset.
|
||||
*/
|
||||
private $convolves = array(
|
||||
'lighten' => '0,0,0, 0,12,0, 0,0,0, 9, 0',
|
||||
@@ -276,30 +276,50 @@ class CImage
|
||||
|
||||
|
||||
/**
|
||||
* Resize strategy to fill extra area with background color.
|
||||
* Resize strategy to fill extra area with background color.
|
||||
* True or false.
|
||||
*/
|
||||
private $fillToFit;
|
||||
|
||||
|
||||
/**
|
||||
* Used with option area to set which parts of the image to use.
|
||||
* Used with option area to set which parts of the image to use.
|
||||
*/
|
||||
private $offset;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calculate target dimension for image when using fill-to-fit resize strategy.
|
||||
*/
|
||||
* Calculate target dimension for image when using fill-to-fit resize strategy.
|
||||
*/
|
||||
private $fillWidth;
|
||||
private $fillHeight;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allow remote file download, default is to disallow remote file download.
|
||||
*/
|
||||
private $allowRemote = false;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Pattern to recognize a remote file.
|
||||
*/
|
||||
private $remotePattern = '#^[http|https]://#';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Use the cache if true, set to false to ignore the cached file.
|
||||
*/
|
||||
private $useCache = true;
|
||||
|
||||
|
||||
/**
|
||||
* Properties, the class is mutable and the method setOptions()
|
||||
* decides (partly) what properties are created.
|
||||
* decides (partly) what properties are created.
|
||||
*
|
||||
* @todo Clean up these and check if and how they are used
|
||||
*/
|
||||
@@ -313,7 +333,6 @@ class CImage
|
||||
public $filters;
|
||||
private $type; // Calculated from source image
|
||||
private $attr; // Calculated from source image
|
||||
private $useCache; // Use the cache if true, set to false to ignore the cached file.
|
||||
private $useOriginal; // Use original image if possible
|
||||
|
||||
|
||||
@@ -338,7 +357,8 @@ class CImage
|
||||
/**
|
||||
* Set verbose mode.
|
||||
*
|
||||
* @param boolean $mode true or false to enable and disable versbose mode, default is true.
|
||||
* @param boolean $mode true or false to enable and disable verbose mode,
|
||||
* default is true.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -347,8 +367,84 @@ class CImage
|
||||
$this->verbose = $mode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set save folder, base folder for saving cache files.
|
||||
*
|
||||
* @todo clean up how $this->saveFolder is used in other methods.
|
||||
*
|
||||
* @param string $path where to store cached files.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSaveFolder($path)
|
||||
{
|
||||
$this->saveFolder = $path;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Use cache or not.
|
||||
*
|
||||
* @todo clean up how $this->noCache is used in other methods.
|
||||
*
|
||||
* @param string $use true or false to use cache.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function useCache($use = true)
|
||||
{
|
||||
$this->useCache = $use;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allow or disallow remote image download.
|
||||
*
|
||||
* @param boolean $allow true or false to enable and disable.
|
||||
* @param string $pattern to use to detect if its a remote file.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRemoteDownload($allow, $pattern = null)
|
||||
{
|
||||
$this->allowRemote = $allow;
|
||||
$this->remotePattern = $pattern ? $pattern : $this->remotePattern;
|
||||
|
||||
$this->log("Set remote download to: "
|
||||
. ($this->allowRemote ? "true" : "false")
|
||||
. " using pattern "
|
||||
. $this->remotePattern);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if the image resource is a remote file or not.
|
||||
*
|
||||
* @param string $src check if src is remote.
|
||||
*
|
||||
* @return boolean true if $src is a remote file, else false.
|
||||
*/
|
||||
public function isRemoteSource($src)
|
||||
{
|
||||
$remote = $this->allowRemote
|
||||
&& preg_match($this->remotePattern, $src);
|
||||
|
||||
$this->log("Detected remote image: " . ($remote ? "true" : "false"));
|
||||
|
||||
return $remote;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if file extension is valid as a file extension.
|
||||
@@ -366,9 +462,9 @@ class CImage
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set src file.
|
||||
*
|
||||
@@ -381,7 +477,26 @@ class CImage
|
||||
{
|
||||
if (!isset($src)) {
|
||||
return $this;
|
||||
} else if (!isset($dir)) {
|
||||
}
|
||||
|
||||
if ($this->isRemoteSource($src)) {
|
||||
$remote = new CRemoteImage();
|
||||
|
||||
$cache = $this->saveFolder . "/remote/";
|
||||
if (!is_writable($cache)) {
|
||||
$this->log("The remote cache is not writable.");
|
||||
}
|
||||
|
||||
$remote->setCache($cache);
|
||||
$remote->useCache($this->useCache);
|
||||
$src = $remote->download($src);
|
||||
$this->log("Remote HTTP status: " . $remote->getStatus());
|
||||
$this->log("Remote item has local cached file: $src");
|
||||
$this->log("Remote details on cache:" . print_r($remote->getDetails(), true));
|
||||
$dir = null;
|
||||
}
|
||||
|
||||
if (!isset($dir)) {
|
||||
$dir = dirname($src);
|
||||
$src = basename($src);
|
||||
}
|
||||
@@ -391,14 +506,14 @@ class CImage
|
||||
$this->pathToImage = $this->imageFolder . '/' . $this->imageSrc;
|
||||
$this->fileExtension = strtolower(pathinfo($this->pathToImage, PATHINFO_EXTENSION));
|
||||
//$this->extension = $this->fileExtension;
|
||||
|
||||
|
||||
$this->checkFileExtension($this->fileExtension);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set target file.
|
||||
*
|
||||
@@ -424,12 +539,12 @@ class CImage
|
||||
// Sanitize filename
|
||||
$this->cacheFileName = preg_replace('/^a-zA-Z0-9\.-_/', '', $this->cacheFileName);
|
||||
$this->log("The cache file name is: " . $this->cacheFileName);
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set options to use when processing image.
|
||||
*
|
||||
@@ -517,7 +632,7 @@ class CImage
|
||||
$filter["arg{$i}"] = $parts[$i];
|
||||
} else {
|
||||
throw new Exception(
|
||||
'Missing arg to filter, review how many arguments are needed at
|
||||
'Missing arg to filter, review how many arguments are needed at
|
||||
http://php.net/manual/en/function.imagefilter.php'
|
||||
);
|
||||
}
|
||||
@@ -553,7 +668,7 @@ class CImage
|
||||
* @param string $name the name of the filter.
|
||||
*
|
||||
* @return array with filter settings
|
||||
* @throws Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
private function mapFilter($name)
|
||||
{
|
||||
@@ -578,8 +693,8 @@ class CImage
|
||||
throw new Exception('No such filter.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load image details from original image file.
|
||||
@@ -612,8 +727,8 @@ class CImage
|
||||
|
||||
|
||||
/**
|
||||
* Init new width and height and do some sanity checks on constraints, before any
|
||||
* processing can be done.
|
||||
* Init new width and height and do some sanity checks on constraints, before any
|
||||
* processing can be done.
|
||||
*
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
@@ -746,12 +861,12 @@ class CImage
|
||||
|
||||
// Crop-to-fit and both new width and height are set.
|
||||
if (($this->cropToFit || $this->fillToFit) && isset($this->newWidth) && isset($this->newHeight)) {
|
||||
|
||||
|
||||
// Use newWidth and newHeigh as width/height, image should fit in box.
|
||||
$this->log("Use newWidth and newHeigh as width/height, image should fit in box.");
|
||||
|
||||
} elseif (isset($this->newWidth) && isset($this->newHeight)) {
|
||||
|
||||
|
||||
// Both new width and height are set.
|
||||
// Use newWidth and newHeigh as max width/height, image should not be larger.
|
||||
$ratioWidth = $width / $this->newWidth;
|
||||
@@ -760,23 +875,23 @@ class CImage
|
||||
$this->newWidth = round($width / $ratio);
|
||||
$this->newHeight = round($height / $ratio);
|
||||
$this->log("New width and height was set.");
|
||||
|
||||
|
||||
} elseif (isset($this->newWidth)) {
|
||||
|
||||
|
||||
// Use new width as max-width
|
||||
$factor = (float)$this->newWidth / (float)$width;
|
||||
$this->newHeight = round($factor * $height);
|
||||
$this->log("New width was set.");
|
||||
|
||||
|
||||
} elseif (isset($this->newHeight)) {
|
||||
|
||||
|
||||
// Use new height as max-hight
|
||||
$factor = (float)$this->newHeight / (float)$height;
|
||||
$this->newWidth = round($factor * $width);
|
||||
$this->log("New height was set.");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Get image dimensions for pre-resize image.
|
||||
if ($this->cropToFit || $this->fillToFit) {
|
||||
|
||||
@@ -785,7 +900,7 @@ class CImage
|
||||
$ratioHeight = $height / $this->newHeight;
|
||||
|
||||
if ($this->cropToFit) {
|
||||
|
||||
|
||||
// Use newWidth and newHeigh as defined width/height,
|
||||
// image should fit the area.
|
||||
$this->log("Crop to fit.");
|
||||
@@ -793,9 +908,9 @@ class CImage
|
||||
$this->cropWidth = round($width / $ratio);
|
||||
$this->cropHeight = round($height / $ratio);
|
||||
$this->log("Crop width, height, ratio: $this->cropWidth x $this->cropHeight ($ratio).");
|
||||
|
||||
|
||||
} else if ($this->fillToFit) {
|
||||
|
||||
|
||||
// Use newWidth and newHeigh as defined width/height,
|
||||
// image should fit the area.
|
||||
$this->log("Fill to fit.");
|
||||
@@ -834,7 +949,7 @@ class CImage
|
||||
/**
|
||||
* Re-calculate image dimensions when original image dimension has changed.
|
||||
*
|
||||
* @return $this
|
||||
* @return $this
|
||||
*/
|
||||
public function reCalculateDimensions()
|
||||
{
|
||||
@@ -857,7 +972,7 @@ class CImage
|
||||
*
|
||||
* @param string $saveas extension to save image as
|
||||
*
|
||||
* @return $this
|
||||
* @return $this
|
||||
*/
|
||||
public function setSaveAsExtension($saveAs = null)
|
||||
{
|
||||
@@ -879,7 +994,7 @@ class CImage
|
||||
* Set JPEG quality to use when saving image
|
||||
*
|
||||
* @param int $quality as the quality to set.
|
||||
*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setJpegQuality($quality = null)
|
||||
@@ -906,7 +1021,7 @@ class CImage
|
||||
* Set PNG compressen algorithm to use when saving image
|
||||
*
|
||||
* @param int $compress as the algorithm to use.
|
||||
*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPngCompression($compress = null)
|
||||
@@ -967,7 +1082,7 @@ class CImage
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate filename to save file in cache.
|
||||
@@ -1000,7 +1115,7 @@ class CImage
|
||||
$crop = $this->crop
|
||||
? '_c' . $this->crop['width'] . '-' . $this->crop['height'] . '-' . $this->crop['start_x'] . '-' . $this->crop['start_y']
|
||||
: null;
|
||||
|
||||
|
||||
$filters = null;
|
||||
if (isset($this->filters)) {
|
||||
foreach ($this->filters as $filter) {
|
||||
@@ -1017,7 +1132,7 @@ class CImage
|
||||
$emboss = $this->emboss ? 'e' : null;
|
||||
$blur = $this->blur ? 'b' : null;
|
||||
$palette = $this->palette ? 'p' : null;
|
||||
|
||||
|
||||
$autoRotate = $this->autoRotate ? 'ar' : null;
|
||||
|
||||
$this->extension = isset($this->extension)
|
||||
@@ -1058,7 +1173,7 @@ class CImage
|
||||
|
||||
/**
|
||||
* Use cached version of image, if possible.
|
||||
*
|
||||
*
|
||||
* @param boolean $useCache is default true, set to false to avoid using cached object.
|
||||
*
|
||||
* @return $this
|
||||
@@ -1068,7 +1183,7 @@ class CImage
|
||||
if ($useCache && is_readable($this->cacheFileName)) {
|
||||
$fileTime = filemtime($this->pathToImage);
|
||||
$cacheTime = filemtime($this->cacheFileName);
|
||||
|
||||
|
||||
if ($fileTime <= $cacheTime) {
|
||||
if ($this->useCache) {
|
||||
if ($this->verbose) {
|
||||
@@ -1090,7 +1205,7 @@ class CImage
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Error message when failing to load somehow corrupt image.
|
||||
*
|
||||
@@ -1107,11 +1222,11 @@ class CImage
|
||||
case 'jpeg':
|
||||
$this->image = imagecreatefromjpeg($this->pathToImage);
|
||||
break;
|
||||
|
||||
|
||||
case 'gif':
|
||||
$this->image = imagecreatefromgif($this->pathToImage);
|
||||
break;
|
||||
|
||||
|
||||
case 'png':
|
||||
$this->image = imagecreatefrompng($this->pathToImage);
|
||||
break;
|
||||
@@ -1145,19 +1260,19 @@ class CImage
|
||||
$this->image = @imagecreatefromjpeg($this->pathToImage);
|
||||
$this->image or $this->failedToLoad();
|
||||
break;
|
||||
|
||||
|
||||
case 'gif':
|
||||
$this->image = @imagecreatefromgif($this->pathToImage);
|
||||
$this->image or $this->failedToLoad();
|
||||
break;
|
||||
|
||||
|
||||
case 'png':
|
||||
$this->image = @imagecreatefrompng($this->pathToImage);
|
||||
$this->image or $this->failedToLoad();
|
||||
|
||||
$type = $this->getPngType();
|
||||
$hasFewColors = imagecolorstotal($this->image);
|
||||
|
||||
|
||||
if ($type == self::PNG_RGB_PALETTE || ($hasFewColors > 0 && $hasFewColors <= 256)) {
|
||||
if ($this->verbose) {
|
||||
$this->log("Handle this image as a palette image.");
|
||||
@@ -1193,7 +1308,7 @@ class CImage
|
||||
$pngType = ord(file_get_contents($this->pathToImage, false, null, 25, 1));
|
||||
|
||||
switch ($pngType) {
|
||||
|
||||
|
||||
case self::PNG_GREYSCALE:
|
||||
$this->log("PNG is type 0, Greyscale.");
|
||||
break;
|
||||
@@ -1209,7 +1324,7 @@ class CImage
|
||||
case self::PNG_GREYSCALE_ALPHA:
|
||||
$this->Log("PNG is type 4, Greyscale with alpha channel");
|
||||
break;
|
||||
|
||||
|
||||
case self::PNG_RGB_ALPHA:
|
||||
$this->Log("PNG is type 6, RGB with alpha channel (PNG 32-bit)");
|
||||
break;
|
||||
@@ -1223,12 +1338,12 @@ class CImage
|
||||
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Calculate number of colors in an image.
|
||||
*
|
||||
* @param resource $im the image.
|
||||
*
|
||||
* @return int
|
||||
* @return int
|
||||
*/
|
||||
private function colorsTotal($im)
|
||||
{
|
||||
@@ -1304,7 +1419,7 @@ class CImage
|
||||
|
||||
// Only use a specified area of the image, $this->offset is defining the area to use
|
||||
if (isset($this->offset)) {
|
||||
|
||||
|
||||
$this->log("Offset for area to use, cropping it width={$this->offset['width']}, height={$this->offset['height']}, start_x={$this->offset['left']}, start_y={$this->offset['top']}");
|
||||
$img = $this->CreateImageKeepTransparency($this->offset['width'], $this->offset['height']);
|
||||
imagecopy($img, $this->image, 0, 0, $this->offset['left'], $this->offset['top'], $this->offset['width'], $this->offset['height']);
|
||||
@@ -1312,7 +1427,7 @@ class CImage
|
||||
$this->width = $this->offset['width'];
|
||||
$this->height = $this->offset['height'];
|
||||
}
|
||||
|
||||
|
||||
if ($this->crop) {
|
||||
|
||||
// Do as crop, take only part of image
|
||||
@@ -1329,15 +1444,15 @@ class CImage
|
||||
// likely to be more readable code.
|
||||
// The code is more or leass equal in below crop-to-fit, fill-to-fit and stretch
|
||||
}
|
||||
|
||||
|
||||
if ($this->cropToFit) {
|
||||
|
||||
|
||||
// Resize by crop to fit
|
||||
$this->log("Resizing using strategy - Crop to fit");
|
||||
|
||||
if (!$this->upscale && ($this->width < $this->newWidth || $this->height < $this->newHeight)) {
|
||||
$this->log("Resizing - smaller image, do not upscale.");
|
||||
|
||||
|
||||
$cropX = round(($this->cropWidth/2) - ($this->newWidth/2));
|
||||
$cropY = round(($this->cropHeight/2) - ($this->newHeight/2));
|
||||
|
||||
@@ -1347,7 +1462,7 @@ class CImage
|
||||
if ($this->newWidth > $this->width) {
|
||||
$posX = round(($this->newWidth - $this->width) / 2);
|
||||
}
|
||||
|
||||
|
||||
if ($this->newHeight > $this->height) {
|
||||
$posY = round(($this->newHeight - $this->height) / 2);
|
||||
}
|
||||
@@ -1366,9 +1481,9 @@ class CImage
|
||||
$this->image = $imageResized;
|
||||
$this->width = $this->newWidth;
|
||||
$this->height = $this->newHeight;
|
||||
|
||||
|
||||
} else if ($this->fillToFit) {
|
||||
|
||||
|
||||
// Resize by fill to fit
|
||||
$this->log("Resizing using strategy - Fill to fit");
|
||||
|
||||
@@ -1388,13 +1503,13 @@ class CImage
|
||||
if (!$this->upscale
|
||||
&& ($this->width < $this->newWidth || $this->height < $this->newHeight)
|
||||
) {
|
||||
|
||||
|
||||
$this->log("Resizing - smaller image, do not upscale.");
|
||||
$posX = round(($this->fillWidth - $this->width) / 2);
|
||||
$posY = round(($this->fillHeight - $this->height) / 2);
|
||||
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
|
||||
imagecopy($imageResized, $this->image, $posX, $posY, 0, 0, $this->fillWidth, $this->fillHeight);
|
||||
|
||||
|
||||
} else {
|
||||
$imgPreFill = $this->CreateImageKeepTransparency($this->fillWidth, $this->fillHeight);
|
||||
$imageResized = $this->CreateImageKeepTransparency($this->newWidth, $this->newHeight);
|
||||
@@ -1405,9 +1520,9 @@ class CImage
|
||||
$this->image = $imageResized;
|
||||
$this->width = $this->newWidth;
|
||||
$this->height = $this->newHeight;
|
||||
|
||||
|
||||
} else if (!($this->newWidth == $this->width && $this->newHeight == $this->height)) {
|
||||
|
||||
|
||||
// Resize it
|
||||
$this->log("Resizing, new height and/or width");
|
||||
|
||||
@@ -1473,24 +1588,24 @@ class CImage
|
||||
|
||||
// Apply filters
|
||||
if (isset($this->filters) && is_array($this->filters)) {
|
||||
|
||||
|
||||
foreach ($this->filters as $filter) {
|
||||
$this->log("Applying filter {$filter['type']}.");
|
||||
|
||||
|
||||
switch ($filter['argc']) {
|
||||
|
||||
|
||||
case 0:
|
||||
imagefilter($this->image, $filter['type']);
|
||||
break;
|
||||
|
||||
|
||||
case 1:
|
||||
imagefilter($this->image, $filter['type'], $filter['arg1']);
|
||||
break;
|
||||
|
||||
|
||||
case 2:
|
||||
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2']);
|
||||
break;
|
||||
|
||||
|
||||
case 3:
|
||||
imagefilter($this->image, $filter['type'], $filter['arg1'], $filter['arg2'], $filter['arg3']);
|
||||
break;
|
||||
@@ -1535,11 +1650,11 @@ class CImage
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rotate image using angle.
|
||||
*
|
||||
*
|
||||
* @param float $angle to rotate image.
|
||||
* @param int $anglebgColor to fill image with if needed.
|
||||
*
|
||||
@@ -1551,7 +1666,7 @@ class CImage
|
||||
|
||||
$color = $this->getBackgroundColor();
|
||||
$this->image = imagerotate($this->image, $angle, $color);
|
||||
|
||||
|
||||
$this->width = imagesx($this->image);
|
||||
$this->height = imagesy($this->image);
|
||||
|
||||
@@ -1564,7 +1679,7 @@ class CImage
|
||||
|
||||
/**
|
||||
* Rotate image using information in EXIF.
|
||||
*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function rotateExif()
|
||||
@@ -1599,7 +1714,7 @@ class CImage
|
||||
} else {
|
||||
$this->log("Autorotate ignored, no orientation in EXIF.");
|
||||
}
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -1633,7 +1748,7 @@ class CImage
|
||||
|
||||
/**
|
||||
* Sharpen image using image convolution.
|
||||
*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sharpenImage()
|
||||
@@ -1646,7 +1761,7 @@ class CImage
|
||||
|
||||
/**
|
||||
* Emboss image using image convolution.
|
||||
*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function embossImage()
|
||||
@@ -1659,7 +1774,7 @@ class CImage
|
||||
|
||||
/**
|
||||
* Blur image using image convolution.
|
||||
*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function blurImage()
|
||||
@@ -1672,7 +1787,7 @@ class CImage
|
||||
|
||||
/**
|
||||
* Create convolve expression and return arguments for image convolution.
|
||||
*
|
||||
*
|
||||
* @param string $expression constant string which evaluates to a list of
|
||||
* 11 numbers separated by komma or such a list.
|
||||
*
|
||||
@@ -1691,17 +1806,17 @@ class CImage
|
||||
// Expect list of 11 numbers, split by , and build up arguments
|
||||
if (count($part) != 11) {
|
||||
throw new Exception(
|
||||
"Missmatch in argument convolve. Expected comma-separated string with
|
||||
"Missmatch in argument convolve. Expected comma-separated string with
|
||||
11 float values. Got $expression."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
array_walk($part, function ($item, $key) {
|
||||
if (!is_numeric($item)) {
|
||||
throw new Exception("Argument to convolve expression should be float but is not.");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return array(
|
||||
array(
|
||||
array($part[0], $part[1], $part[2]),
|
||||
@@ -1717,7 +1832,7 @@ class CImage
|
||||
|
||||
/**
|
||||
* Add custom expressions (or overwrite existing) for image convolution.
|
||||
*
|
||||
*
|
||||
* @param array $options Key value array with strings to be converted
|
||||
* to convolution expressions.
|
||||
*
|
||||
@@ -1733,7 +1848,7 @@ class CImage
|
||||
|
||||
/**
|
||||
* Image convolution.
|
||||
*
|
||||
*
|
||||
* @param string $options A string with 11 float separated by comma.
|
||||
*
|
||||
* @return $this
|
||||
@@ -1752,7 +1867,7 @@ class CImage
|
||||
list($matrix, $divisor, $offset) = $this->createConvolveArguments($option);
|
||||
imageconvolution($this->image, $matrix, $divisor, $offset);
|
||||
}
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -1842,7 +1957,7 @@ class CImage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a image and keep transparency for png and gifs.
|
||||
@@ -1869,10 +1984,10 @@ class CImage
|
||||
return $img;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set optimizing and post-processing options.
|
||||
* Set optimizing and post-processing options.
|
||||
*
|
||||
* @param array $options with config for postprocessing with external tools.
|
||||
*
|
||||
@@ -1897,7 +2012,7 @@ class CImage
|
||||
} else {
|
||||
$this->pngDeflateCmd = null;
|
||||
}
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -1921,12 +2036,12 @@ class CImage
|
||||
or $this->raiseError('Target directory is not writable.');
|
||||
|
||||
switch(strtolower($this->extension)) {
|
||||
|
||||
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
$this->Log("Saving image as JPEG to cache using quality = {$this->quality}.");
|
||||
imagejpeg($this->image, $this->cacheFileName, $this->quality);
|
||||
|
||||
|
||||
// Use JPEG optimize if defined
|
||||
if ($this->jpegOptimizeCmd) {
|
||||
if ($this->verbose) {
|
||||
@@ -1942,10 +2057,8 @@ class CImage
|
||||
break;
|
||||
|
||||
case 'gif':
|
||||
if ($this->saveFolder) {
|
||||
$this->Log("Saving image as GIF to cache.");
|
||||
imagegif($this->image, $this->cacheFileName);
|
||||
}
|
||||
$this->Log("Saving image as GIF to cache.");
|
||||
imagegif($this->image, $this->cacheFileName);
|
||||
break;
|
||||
|
||||
case 'png':
|
||||
@@ -1955,7 +2068,7 @@ class CImage
|
||||
imagealphablending($this->image, false);
|
||||
imagesavealpha($this->image, true);
|
||||
imagepng($this->image, $this->cacheFileName, $this->compress);
|
||||
|
||||
|
||||
// Use external program to filter PNG, if defined
|
||||
if ($this->pngFilterCmd) {
|
||||
if ($this->verbose) {
|
||||
@@ -2039,17 +2152,17 @@ class CImage
|
||||
}
|
||||
|
||||
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified) {
|
||||
|
||||
|
||||
if ($this->verbose) {
|
||||
$this->log("304 not modified");
|
||||
$this->verboseOutput();
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
header("HTTP/1.0 304 Not Modified");
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
if ($this->verbose) {
|
||||
$this->log("Last modified: " . $gmdate . " GMT");
|
||||
$this->verboseOutput();
|
||||
@@ -2064,7 +2177,7 @@ class CImage
|
||||
header('Content-type: ' . $mime);
|
||||
readfile($file);
|
||||
}
|
||||
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -2108,7 +2221,7 @@ class CImage
|
||||
if (defined("JSON_PRETTY_PRINT") && defined("JSON_UNESCAPED_SLASHES")) {
|
||||
$options = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES;
|
||||
}
|
||||
|
||||
|
||||
return json_encode($details, $options);
|
||||
}
|
||||
|
||||
@@ -2129,9 +2242,9 @@ class CImage
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Do verbose output and print out the log and the actual images.
|
||||
*
|
||||
@@ -2146,7 +2259,7 @@ class CImage
|
||||
|
||||
$included = get_included_files();
|
||||
$this->log("Included files: " . count($included));
|
||||
|
||||
|
||||
foreach ($this->log as $val) {
|
||||
if (is_array($val)) {
|
||||
foreach ($val as $val1) {
|
||||
@@ -2175,7 +2288,7 @@ EOD;
|
||||
*
|
||||
* @param string $message the error message to display.
|
||||
*
|
||||
* @return void
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function raiseError($message)
|
||||
|
330
CRemoteImage.php
Normal file
330
CRemoteImage.php
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
/**
|
||||
* Get a image from a remote server using HTTP GET and If-Modified-Since.
|
||||
*
|
||||
*/
|
||||
class CRemoteImage
|
||||
{
|
||||
/**
|
||||
* Path to cache files.
|
||||
*/
|
||||
private $saveFolder = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Use cache or not.
|
||||
*/
|
||||
private $useCache = true;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* HTTP object to aid in download file.
|
||||
*/
|
||||
private $http;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Status of the HTTP request.
|
||||
*/
|
||||
private $status;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Defalt age for cached items 60*60*24*7.
|
||||
*/
|
||||
private $defaultMaxAge = 604800;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Url of downloaded item.
|
||||
*/
|
||||
private $url;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base name of cache file for downloaded item.
|
||||
*/
|
||||
private $fileName;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Filename for json-file with details of cached item.
|
||||
*/
|
||||
private $fileJson;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Filename for image-file.
|
||||
*/
|
||||
private $fileImage;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Cache details loaded from file.
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get status of last HTTP request.
|
||||
*
|
||||
* @return int as status
|
||||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get JSON details for cache item.
|
||||
*
|
||||
* @return array with json details on cache.
|
||||
*/
|
||||
public function getDetails()
|
||||
{
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the path to the cache directory.
|
||||
*
|
||||
* @param boolean $use true to use the cache and false to ignore cache.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCache($path)
|
||||
{
|
||||
$this->saveFolder = $path;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decide if the cache should be used or not before trying to download
|
||||
* a remote file.
|
||||
*
|
||||
* @param boolean $use true to use the cache and false to ignore cache.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function useCache($use = true)
|
||||
{
|
||||
$this->useCache = $use;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Translate a content type to a file extension.
|
||||
*
|
||||
* @param string $type a valid content type.
|
||||
*
|
||||
* @return string as file extension or false if no match.
|
||||
*/
|
||||
function contentTypeToFileExtension($type) {
|
||||
$extension = array(
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/gif' => 'gif',
|
||||
);
|
||||
|
||||
return isset($extension[$type])
|
||||
? $extension[$type]
|
||||
: false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set header fields.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
function setHeaderFields() {
|
||||
$this->http->setHeader("User-Agent", "CImage/0.6 (PHP/". phpversion() . " cURL)");
|
||||
$this->http->setHeader("Accept", "image/jpeg,image/png,image/gif");
|
||||
|
||||
if ($this->useCache) {
|
||||
$this->http->setHeader("Cache-Control", "max-age=0");
|
||||
} else {
|
||||
$this->http->setHeader("Cache-Control", "no-cache");
|
||||
$this->http->setHeader("Pragma", "no-cache");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Save downloaded resource to cache.
|
||||
*
|
||||
* @return string as path to saved file or false if not saved.
|
||||
*/
|
||||
function save() {
|
||||
|
||||
$this->cache = array();
|
||||
$date = $this->http->getDate(time());
|
||||
$maxAge = $this->http->getMaxAge($this->defaultMaxAge);
|
||||
$lastModified = $this->http->getLastModified();
|
||||
$type = $this->http->getContentType();
|
||||
$extension = $this->contentTypeToFileExtension($type);
|
||||
|
||||
$this->cache['Date'] = gmdate("D, d M Y H:i:s T", $date);
|
||||
$this->cache['Max-Age'] = $maxAge;
|
||||
$this->cache['Content-Type'] = $type;
|
||||
$this->cache['File-Extension'] = $extension;
|
||||
|
||||
if ($lastModified) {
|
||||
$this->cache['Last-Modified'] = gmdate("D, d M Y H:i:s T", $lastModified);
|
||||
}
|
||||
|
||||
if ($extension) {
|
||||
|
||||
$this->fileImage = $this->fileName . "." . $extension;
|
||||
|
||||
// Save only if body is a valid image
|
||||
$body = $this->http->getBody();
|
||||
$img = imagecreatefromstring($body);
|
||||
|
||||
if ($img !== false) {
|
||||
file_put_contents($this->fileImage, $body);
|
||||
file_put_contents($this->fileJson, json_encode($this->cache));
|
||||
return $this->fileImage;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Got a 304 and updates cache with new age.
|
||||
*
|
||||
* @return string as path to cached file.
|
||||
*/
|
||||
function updateCacheDetails() {
|
||||
|
||||
$date = $this->http->getDate(time());
|
||||
$maxAge = $this->http->getMaxAge($this->defaultMaxAge);
|
||||
$lastModified = $this->http->getLastModified();
|
||||
|
||||
$this->cache['Date'] = gmdate("D, d M Y H:i:s T", $date);
|
||||
$this->cache['Max-Age'] = $maxAge;
|
||||
|
||||
if ($lastModified) {
|
||||
$this->cache['Last-Modified'] = gmdate("D, d M Y H:i:s T", $lastModified);
|
||||
}
|
||||
|
||||
file_put_contents($this->fileJson, json_encode($this->cache));
|
||||
return $this->fileImage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Download a remote file and keep a cache of downloaded files.
|
||||
*
|
||||
* @param string $url a remote url.
|
||||
*
|
||||
* @return string as path to downloaded file or false if failed.
|
||||
*/
|
||||
function download($url) {
|
||||
|
||||
$this->http = new CHttpGet();
|
||||
$this->url = $url;
|
||||
|
||||
// First check if the cache is valid and can be used
|
||||
$this->loadCacheDetails();
|
||||
|
||||
if ($this->useCache) {
|
||||
$src = $this->getCachedSource();
|
||||
if ($src) {
|
||||
$this->status = 1;
|
||||
return $src;
|
||||
}
|
||||
}
|
||||
|
||||
// Do a HTTP request to download item
|
||||
$this->setHeaderFields();
|
||||
$this->http->setUrl($this->url);
|
||||
$this->http->doGet();
|
||||
|
||||
$this->status = $this->http->getStatus();
|
||||
if ($this->status === 200) {
|
||||
return $this->save();
|
||||
} else if ($this->status === 304) {
|
||||
return $this->updateCacheDetails();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the path to the cached image file if the cache is valid.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function loadCacheDetails()
|
||||
{
|
||||
$cacheFile = str_replace(["/", ":", "#", ".", "?"], "-", $this->url);
|
||||
$this->fileName = $this->saveFolder . $cacheFile;
|
||||
$this->fileJson = $this->fileName . ".json";
|
||||
$this->cache = json_decode(file_get_contents($this->fileJson), true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the path to the cached image file if the cache is valid.
|
||||
*
|
||||
* @return string as the path ot the image file or false if no cache.
|
||||
*/
|
||||
public function getCachedSource()
|
||||
{
|
||||
$this->fileImage = $this->fileName . "." . $this->cache['File-Extension'];
|
||||
$imageExists = is_readable($this->fileImage);
|
||||
|
||||
// Is cache valid?
|
||||
$date = strtotime($this->cache['Date']);
|
||||
$maxAge = $this->cache['Max-Age'];
|
||||
$now = time();
|
||||
if ($imageExists && $date + $maxAge > $now) {
|
||||
return $this->fileImage;
|
||||
}
|
||||
|
||||
// Prepare for a 304 if available
|
||||
if ($imageExists && isset($this->cache['Last-Modified'])) {
|
||||
$this->http->setHeader("If-Modified-Since", $this->cache['Last-Modified']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -133,6 +133,21 @@ $img->setVerbose($verbose);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allow or disallow remote download of images from other servers.
|
||||
*
|
||||
*/
|
||||
$allowRemote = $config['remote_allow'];
|
||||
|
||||
if ($allowRemote) {
|
||||
$pattern = isset($config['remote_pattern'])
|
||||
? $config['remote_pattern']
|
||||
: null;
|
||||
$img->setRemoteDownload($allowRemote, $pattern);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* shortcut, sc - extend arguments with a constant value, defined
|
||||
* in config-file.
|
||||
@@ -144,7 +159,7 @@ verbose("shortcut = $shortcut");
|
||||
if (isset($shortcut)
|
||||
&& isset($config['shortcut'])
|
||||
&& isset($config['shortcut'][$shortcut])) {
|
||||
|
||||
|
||||
parse_str($config['shortcut'][$shortcut], $get);
|
||||
verbose("shortcut-constant = {$config['shortcut'][$shortcut]}");
|
||||
$_GET = array_merge($_GET, $get);
|
||||
@@ -164,21 +179,25 @@ preg_match($config['valid_filename'], $srcImage)
|
||||
or errorPage('Filename contains invalid characters.');
|
||||
|
||||
|
||||
// Check that the image is a file below the directory 'image_path'.
|
||||
if ($config['image_path_constraint']) {
|
||||
|
||||
if ($allowRemote && $img->isRemoteSource($srcImage)) {
|
||||
|
||||
// If source is a remote file, ignore local file checks.
|
||||
|
||||
} else if ($config['image_path_constraint']) {
|
||||
|
||||
// Check that the image is a file below the directory 'image_path'.
|
||||
$pathToImage = realpath($config['image_path'] . $srcImage);
|
||||
$imageDir = realpath($config['image_path']);
|
||||
|
||||
is_file($pathToImage)
|
||||
or errorPage(
|
||||
'Source image is not a valid file, check the filename and that a
|
||||
'Source image is not a valid file, check the filename and that a
|
||||
matching file exists on the filesystem.'
|
||||
);
|
||||
|
||||
substr_compare($imageDir, $pathToImage, 0, strlen($imageDir)) == 0
|
||||
or errorPage(
|
||||
'Security constraint: Source image is not below the directory "image_path"
|
||||
'Security constraint: Source image is not below the directory "image_path"
|
||||
as specified in the config file img_config.php.'
|
||||
);
|
||||
}
|
||||
@@ -374,7 +393,7 @@ verbose("quality = $quality");
|
||||
*/
|
||||
$compress = get(array('compress', 'co'));
|
||||
|
||||
|
||||
|
||||
is_null($compress)
|
||||
or ($compress > 0 and $compress <= 9)
|
||||
or errorPage('Compress out of range');
|
||||
@@ -519,7 +538,7 @@ verbose("dpr = $dpr");
|
||||
*/
|
||||
$convolve = get('convolve', null);
|
||||
|
||||
// Check if the convolve is matching an existing constant
|
||||
// Check if the convolve is matching an existing constant
|
||||
if ($convolve && isset($config['convolution_constant'])) {
|
||||
$img->addConvolveExpressions($config['convolution_constant']);
|
||||
verbose("convolve constant = " . print_r($config['convolution_constant'], 1));
|
||||
@@ -574,6 +593,8 @@ EOD;
|
||||
* Load, process and output the image
|
||||
*/
|
||||
$img->log("Incoming arguments: " . print_r(verbose(), 1))
|
||||
->setSaveFolder($config['cache_path'])
|
||||
->useCache($useCache)
|
||||
->setSource($srcImage, $config['image_path'])
|
||||
->setOptions(
|
||||
array(
|
||||
@@ -591,7 +612,7 @@ $img->log("Incoming arguments: " . print_r(verbose(), 1))
|
||||
// Pre-processing, before resizing is done
|
||||
'scale' => $scale,
|
||||
'rotateBefore' => $rotateBefore,
|
||||
'autoRotate' => $autoRotate,
|
||||
'autoRotate' => $autoRotate,
|
||||
|
||||
// General processing options
|
||||
'bgColor' => $bgColor,
|
||||
|
@@ -1,14 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Configuration for img.php, name the config file the same as your img.php and
|
||||
* append _config. If you are testing out some in imgtest.php then label that
|
||||
* Configuration for img.php, name the config file the same as your img.php and
|
||||
* append _config. If you are testing out some in imgtest.php then label that
|
||||
* config-file imgtest_config.php.
|
||||
*
|
||||
*/
|
||||
include __DIR__ . "/../CHttpGet.php";
|
||||
include __DIR__ . "/../CRemoteImage.php";
|
||||
|
||||
return array(
|
||||
|
||||
/**
|
||||
* Paths, where are all the stuff I should use?
|
||||
* Paths, where are all the stuff I should use?
|
||||
* Append ending slash on directories.
|
||||
*/
|
||||
'cimage_class' => __DIR__ . '/../CImage.php',
|
||||
@@ -19,7 +22,7 @@ return array(
|
||||
|
||||
/**
|
||||
* Check that the imagefile is a file below 'image_path' using realpath().
|
||||
* Security constraint to avoid reaching images outside image_path.
|
||||
* Security constraint to avoid reaching images outside image_path.
|
||||
* This means that symbolic links to images outside the image_path will fail.
|
||||
*/
|
||||
'image_path_constraint' => true,
|
||||
@@ -29,13 +32,22 @@ return array(
|
||||
/**
|
||||
* A regexp for validating characters in the image filename.
|
||||
*/
|
||||
'valid_filename' => '#^[a-z0-9A-Z-/_\.]+$#',
|
||||
'valid_filename' => '#^[a-z0-9A-Z-/_\.:]+$#',
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allow or disallow downloading of remote files, images available on
|
||||
* some remote server. Default is to disallow.
|
||||
*/
|
||||
'remote_allow' => true,
|
||||
'remote_pattern' => '#^http#',
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set default timezone, it defaults to UTC if not specified.
|
||||
*
|
||||
*
|
||||
*/
|
||||
//'default_timezone' => 'UTC',
|
||||
|
||||
@@ -43,9 +55,9 @@ return array(
|
||||
|
||||
/**
|
||||
* Max image dimensions, larger dimensions results in 404.
|
||||
* This is basically a security constraint to avoid using resources on creating
|
||||
* This is basically a security constraint to avoid using resources on creating
|
||||
* large (unwanted) images.
|
||||
*
|
||||
*
|
||||
*/
|
||||
'max_width' => 2000,
|
||||
'max_height' => 2000,
|
||||
@@ -56,7 +68,7 @@ return array(
|
||||
* Set default background color for all images. Override it using
|
||||
* option bgColor.
|
||||
* Colorvalue is 6 digit hex string between 000000-FFFFFF
|
||||
* or 8 digit hex string if using the alpha channel where
|
||||
* or 8 digit hex string if using the alpha channel where
|
||||
* the alpha value is between 00 (opaqe) and 7F (transparent),
|
||||
* that is between 00000000-FFFFFF7F.
|
||||
*
|
||||
@@ -67,8 +79,8 @@ return array(
|
||||
|
||||
|
||||
/**
|
||||
* Post processing of images using external tools, set to true or false
|
||||
* and set command to be executed.
|
||||
* Post processing of images using external tools, set to true or false
|
||||
* and set command to be executed.
|
||||
*/
|
||||
'postprocessing' => array(
|
||||
'png_filter' => false,
|
||||
@@ -84,7 +96,7 @@ return array(
|
||||
|
||||
|
||||
/**
|
||||
* Create custom convolution expressions, matrix 3x3, divisor and
|
||||
* Create custom convolution expressions, matrix 3x3, divisor and
|
||||
* offset.
|
||||
*/
|
||||
'convolution_constant' => array(
|
||||
@@ -104,13 +116,13 @@ return array(
|
||||
|
||||
|
||||
/**
|
||||
* Predefined size constants.
|
||||
* Predefined size constants.
|
||||
*
|
||||
* These can be used together with &width or &height to create a constant value
|
||||
* These can be used together with &width or &height to create a constant value
|
||||
* for a width or height where can be changed in one place.
|
||||
* Useful when your site changes its layout or if you have a grid to fit images into.
|
||||
*
|
||||
* Example:
|
||||
* Example:
|
||||
* &width=w1 // results in width=613
|
||||
* &width=c2 // results in spanning two columns with a gutter, 30*2+10=70
|
||||
* &width=c24 // results in spanning whole grid 24*30+((24-1)*10)=950
|
||||
@@ -138,8 +150,8 @@ return array(
|
||||
|
||||
|
||||
/**
|
||||
* Predefined aspect ratios.
|
||||
*
|
||||
* Predefined aspect ratios.
|
||||
*
|
||||
*/
|
||||
'aspect_ratio_constant' => function () {
|
||||
return array(
|
||||
@@ -156,7 +168,7 @@ return array(
|
||||
|
||||
|
||||
/**
|
||||
* Set error reporting to match development or production environment
|
||||
* Set error reporting to match development or production environment
|
||||
*/
|
||||
'error_reporting' => function () {
|
||||
error_reporting(-1); // Report all type of errors
|
||||
|
Reference in New Issue
Block a user