11 const CONFIG_USER =
'config/file-mime-user.xml';
12 const CONFIG_SYS =
'config/file-mime.xml';
16 const SPECIFICITY_ANY = 0;
17 const SPECIFICITY_TYPE_ONLY = 1;
18 const SPECIFICITY_TYPE_AND_SUBTYPE = 2;
23 const TARGET_DENY =
'deny';
24 const TARGET_ALLOW =
'allow';
31 protected $inlineRules = array(
32 '*/*' => self::TARGET_DENY
41 public function __construct($configFiles = array())
43 if (count($configFiles) <= 0 || !is_array($configFiles)) {
49 foreach ($configFiles as $configFile) {
50 $this->loadConfig($configFile);
57 public static function isWellformedMIMEType($mime)
59 return (preg_match(
'!^[^ /]+/[^ /]+$!', $mime) === 1);
68 public static function mimeMatch($mime, $pattern)
70 if (!self::isWellformedMIMEType($mime)) {
74 $patternSpecificity = self::getMimePatternSpecificity($pattern);
75 if ($patternSpecificity == self::SPECIFICITY_TYPE_AND_SUBTYPE) {
76 return ($mime === $pattern);
77 } elseif ($patternSpecificity == self::SPECIFICITY_TYPE_ONLY) {
78 $type_slash = substr($pattern, 0, -1);
79 return (substr($mime, strlen($type_slash)) === $type_slash);
89 public function isInlineAllowed($mime)
91 foreach ($this->inlineRules as $rulePattern => $ruleTarget) {
92 if ($this->mimeMatch($mime, $rulePattern)) {
93 return ($ruleTarget === self::TARGET_ALLOW);
105 protected function loadConfig(
$file)
107 if (!is_scalar(
$file)) {
110 if (!file_exists(
$file)) {
113 if (($xml = simplexml_load_file(
$file)) ===
false) {
116 if (!isset($xml->inline)) {
119 $inlineRules = array();
123 foreach ($xml->inline->children() as $rule) {
124 $target = $rule->getName();
125 if ($target != self::TARGET_DENY && $target != self::TARGET_ALLOW) {
128 $attrs = $rule->attributes();
129 if (!isset($attrs[
'type'])) {
132 $type = (string)$attrs[
'type'];
133 $inlineRules[
$type] = $target;
135 return $this->mergeInlineRules($inlineRules);
141 protected function mergeInlineRules($rules)
143 foreach ($rules as $mime => $target) {
144 $this->inlineRules[$mime] = $target;
147 uksort($this->inlineRules,
function ($mime1, $mime2)
149 return $this->cmpMimePatternSpecificity($mime2, $mime1);
160 protected function cmpMimePatternSpecificity($mime1, $mime2)
162 if (($cmp = (self::getMimePatternSpecificity($mime1) - self::getMimePatternSpecificity($mime2))) === 0) {
163 return strcmp($mime1, $mime2);
172 protected static function getMimePatternSpecificity($pattern)
174 $specificity = self::SPECIFICITY_TYPE_AND_SUBTYPE;
175 if ($pattern ===
'*/*') {
176 $specificity = self::SPECIFICITY_ANY;
177 } elseif (substr($pattern, -2) ===
'/*') {
178 $specificity = self::SPECIFICITY_TYPE_ONLY;