/** * Gather/Return information about a resource * * @param mixed $resource Path to file in local FS, URL or file-upload array * @param string $what scheme, host, port, file, MIME type, size, permission, * dirname, basename, filename, extension or type * @return mixed */ function info(&$Model, $resource, $what = null) { extract($this->settings[$Model->alias], EXTR_SKIP); $defaultResource = array('scheme' => null, 'host' => null, 'port' => null, 'file' => null, 'mimeType' => null, 'size' => null, 'pixels' => null, 'permisssion' => null, 'dirname' => null, 'basename' => null, 'filename' => null, 'extension' => null, 'type' => null); /* Currently HTTP is supported only */ if (TransferValidation::url($resource, array('scheme' => 'http'))) { $resource = array_merge($defaultResource, pathinfo(parse_url($resource, PHP_URL_PATH)), array('scheme' => parse_url($resource, PHP_URL_SCHEME), 'host' => parse_url($resource, PHP_URL_HOST), 'port' => parse_url($resource, PHP_URL_PORT), 'file' => $resource, 'type' => 'http-url-remote')); if (!class_exists('HttpSocket')) { App::import('Core', 'HttpSocket'); } $Socket =& new HttpSocket(array('timeout' => 5)); $Socket->request(array('method' => 'HEAD', 'uri' => $resource['file'])); if (empty($Socket->error) && $Socket->response['status']['code'] == 200) { $resource = array_merge($resource, array('size' => $Socket->response['header']['Content-Length'], 'mimeType' => $trustClient ? $Socket->response['header']['Content-Type'] : null, 'permission' => '0004')); } } elseif (MediaValidation::file($resource, false)) { $resource = array_merge($defaultResource, pathinfo($resource), array('file' => $resource, 'host' => 'localhost', 'mimeType' => MimeType::guessType($resource, array('paranoid' => !$trustClient)))); if (TransferValidation::uploadedFile($resource['file'])) { $resource['type'] = 'uploaded-file-local'; } else { $resource['type'] = 'file-local'; } if (is_readable($resource['file'])) { /* * Because there is not better way to determine if resource is an image * first, we suppress a warning that would be thrown here otherwise. */ list($width, $height) = @getimagesize($resource['file']); $resource = array_merge($resource, array('size' => filesize($resource['file']), 'permission' => substr(sprintf('%o', fileperms($resource['file'])), -4), 'pixels' => $width * $height)); } } elseif (TransferValidation::fileUpload($resource)) { $resource = array_merge($defaultResource, pathinfo($resource['name']), array('file' => $resource['name'], 'host' => env('REMOTE_ADDR'), 'size' => $resource['size'], 'mimeType' => $trustClient ? $resource['type'] : null, 'permission' => '0004', 'type' => 'file-upload-remote')); } else { return null; } if (!isset($resource['filename'])) { /* PHP < 5.2.0 */ $length = isset($resource['extension']) ? strlen($resource['extension']) + 1 : 0; $resource['filename'] = substr($resource['basename'], 0, -$length); } if (is_null($what)) { return $resource; } elseif (array_key_exists($what, $resource)) { return $resource[$what]; } return null; }
/** * Checks if resource has (not) one of given MIME types * * This check is less strict in that it isn't sensitive to MIME types with or * without properties or experimental indicators. This holds true for the type * which is subject of the check as well as types provided for $deny and * $allow. I.e. `audio/x-ogg` will be allowed if $allow contains `audio/ogg` * and `video/ogg` works also if $allow contains the stricter `video/x-ogg`. * * @param Model $Model * @param array $field * @param mixed $deny True or * blocks any MIME type, * an array containing MIME types selectively blocks, * false blocks no MIME type * @param mixed $allow True or * allows any extension, * an array containing extensions selectively allows, * false allows no MIME type * @return boolean */ function checkMimeType(&$Model, $field, $deny = false, $allow = true) { extract($this->runtime[$Model->alias]); extract($this->settings[$Model->alias], EXTR_SKIP); foreach (array('source', 'temporary') as $type) { /* * MIME types and trustClient setting * * trust | source | (temporary) | (destination) * ------|----------|---------------------------- * true | x/x | x/x | x/x,null * ------|----------|---------------------------- * false | x/x,null | x/x,null | null */ /* Temporary is optional */ if ($type === 'temporary' && empty(${$type})) { continue; } /* With `trustClient` set to `false` we don't necessarily have a MIME type */ if (!isset(${$type}['mimeType']) && !$trustClient) { continue; } $result = MediaValidation::mimeType(${$type}['mimeType'], $deny, $allow); $result |= MediaValidation::mimeType(Mime_Type::simplify(${$type}['mimeType']), $deny, $allow); return $result; } return true; }
/** * Checks if path is within given locations * * @param string $check Absolute path * @param mixed $allow True or * allows any location, * an array containing absolute paths to locations * @return boolean */ function location($check, $allow = false) { $allow = self::_normalize($allow); if ($allow === true) { return true; } elseif ($allow === false) { return false; } if (!is_array($allow)) { $allow = array($allow); } else { $allow = array_unique($allow); } if (Validation::url($check)) { foreach ($allow as $path) { if (preg_match('/^' . preg_quote($path, '/') . '/', $check)) { return true; } } } elseif (MediaValidation::file($check, false)) { $check = dirname($check); if (!Folder::isAbsolute($check)) { return false; } $Check = new Folder($check); foreach ($allow as $path) { if (!Folder::isAbsolute($path) || Validation::url($path)) { continue; } if ($Check->inPath($path)) { return true; } } } return false; }
/** * Checks if subject is an uploaded file * * @param mixed $check */ static function uploadedFile($check) { return MediaValidation::file($check) && is_uploaded_file($check); }
/** * Checks if resource has (not) one of given MIME types * * This check is less strict in that it isn't sensitive to MIME types with or * without properties or experimental indicators. This holds true for the type * which is subject of the check as well as types provided for $deny and * $allow. I.e. `audio/x-ogg` will be allowed if $allow contains `audio/ogg` * and `video/ogg` works also if $allow contains the stricter `video/x-ogg`. * * @param Model $Model * @param array $field * @param mixed $deny True or * blocks any MIME type, * an array containing MIME types selectively blocks, * false blocks no MIME type * @param mixed $allow True or * allows any extension, * an array containing extensions selectively allows, * false allows no MIME type * @return boolean */ public function checkMimeType(Model $Model, $field, $deny = false, $allow = true) { extract($this->runtime[$Model->alias]); /* @var $source array */ /* @var $temporary string */ /* @var $destination string */ /* @var $hasPerformed boolean */ extract($this->settings[$Model->alias], EXTR_SKIP); /* @var $trustClient boolean */ /* @var $transferDirectory string */ /* @var $createDirectory boolean */ /* @var $alternativeFile integer */ /* @var $overwrite boolean */ foreach (array('source', 'temporary') as $type) { /* * MIME types and trustClient setting * * trust | source | (temporary) | (destination) * ------|----------|---------------------------- * true | x/x | x/x | x/x,null * ------|----------|---------------------------- * false | x/x,null | x/x,null | null */ /* Temporary is optional */ if ($type === 'temporary' && empty(${$type})) { continue; } /* With `trustClient` set to `false` we don't necessarily have a MIME type */ if (!isset(${$type}['mimeType']) && !$trustClient) { continue; } $result = MediaValidation::mimeType(${$type}['mimeType'], $deny, $allow); $result |= MediaValidation::mimeType(Mime_Type::simplify(${$type}['mimeType']), $deny, $allow); return $result; } return true; }
function testFolder() { $file = dirname(__FILE__); $result = MediaValidation::folder($file); $this->assertTrue($result); $file = $this->TestData->getFile('image-jpg.jpg'); $result = MediaValidation::folder($file, false); $this->assertTrue($result); $file = DS . 'i-am-not-a-file.png'; $result = MediaValidation::folder($file); $this->assertFalse($result); $file = DS; $result = MediaValidation::folder($file); $this->assertTrue($result); $file = DS; $result = MediaValidation::folder($file, false); $this->assertTrue($result); $file = DS . DS . DS . DS; $result = MediaValidation::folder($file, false); $this->assertTrue($result); }
public function testFolder() { $file = dirname(__FILE__); $result = MediaValidation::folder($file); $this->assertTrue($result); $file = $this->Data->getFile('image-jpg.jpg'); $result = MediaValidation::folder($file, false); $this->assertTrue($result); $file = $this->Data->settings['base'] . 'i-am-not-a-file.png'; $result = MediaValidation::folder($file); $this->assertFalse($result); $file = TMP; $result = MediaValidation::folder($file); $this->assertTrue($result); $file = TMP; $result = MediaValidation::folder($file, false); $this->assertTrue($result); $file = TMP . DS . DS . DS; $result = MediaValidation::folder($file, false); $this->assertTrue($result); }