- Timestamp:
- 09/30/2024 10:48:16 PM (2 months ago)
- Location:
- trunk/src/wp-includes/SimplePie/src
- Files:
-
- 1 added
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/SimplePie/src/Content/Type/Sniffer.php
r49176 r59141 1 1 <?php 2 2 3 /** 3 4 * SimplePie … … 6 7 * Takes the hard work out of managing a complete RSS/Atom solution. 7 8 * 8 * Copyright (c) 2004-20 16, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors9 * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors 9 10 * All rights reserved. 10 11 * … … 42 43 */ 43 44 45 namespace SimplePie\Content\Type; 44 46 45 47 /** … … 52 54 * 53 55 * 54 * This class can be overloaded with {@see SimplePie::set_content_type_sniffer_class()}56 * This class can be overloaded with {@see \SimplePie\SimplePie::set_content_type_sniffer_class()} 55 57 * 56 58 * @package SimplePie 57 59 * @subpackage HTTP 58 60 */ 59 class S implePie_Content_Type_Sniffer61 class Sniffer 60 62 { 61 /** 62 * File object 63 * 64 * @var SimplePie_File 65 */ 66 var $file; 67 68 /** 69 * Create an instance of the class with the input file 70 * 71 * @param SimplePie_Content_Type_Sniffer $file Input file 72 */ 73 public function __construct($file) 74 { 75 $this->file = $file; 76 } 77 78 /** 79 * Get the Content-Type of the specified file 80 * 81 * @return string Actual Content-Type 82 */ 83 public function get_type() 84 { 85 if (isset($this->file->headers['content-type'])) 86 { 87 if (!isset($this->file->headers['content-encoding']) 88 && ($this->file->headers['content-type'] === 'text/plain' 89 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1' 90 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1' 91 || $this->file->headers['content-type'] === 'text/plain; charset=UTF-8')) 92 { 93 return $this->text_or_binary(); 94 } 95 96 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false) 97 { 98 $official = substr($this->file->headers['content-type'], 0, $pos); 99 } 100 else 101 { 102 $official = $this->file->headers['content-type']; 103 } 104 $official = trim(strtolower($official)); 105 106 if ($official === 'unknown/unknown' 107 || $official === 'application/unknown') 108 { 109 return $this->unknown(); 110 } 111 elseif (substr($official, -4) === '+xml' 112 || $official === 'text/xml' 113 || $official === 'application/xml') 114 { 115 return $official; 116 } 117 elseif (substr($official, 0, 6) === 'image/') 118 { 119 if ($return = $this->image()) 120 { 121 return $return; 122 } 123 124 return $official; 125 } 126 elseif ($official === 'text/html') 127 { 128 return $this->feed_or_html(); 129 } 130 131 return $official; 132 } 133 134 return $this->unknown(); 135 } 136 137 /** 138 * Sniff text or binary 139 * 140 * @return string Actual Content-Type 141 */ 142 public function text_or_binary() 143 { 144 if (substr($this->file->body, 0, 2) === "\xFE\xFF" 145 || substr($this->file->body, 0, 2) === "\xFF\xFE" 146 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF" 147 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF") 148 { 149 return 'text/plain'; 150 } 151 elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body)) 152 { 153 return 'application/octet-stream'; 154 } 155 156 return 'text/plain'; 157 } 158 159 /** 160 * Sniff unknown 161 * 162 * @return string Actual Content-Type 163 */ 164 public function unknown() 165 { 166 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20"); 167 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html' 168 || strtolower(substr($this->file->body, $ws, 5)) === '<html' 169 || strtolower(substr($this->file->body, $ws, 7)) === '<script') 170 { 171 return 'text/html'; 172 } 173 elseif (substr($this->file->body, 0, 5) === '%PDF-') 174 { 175 return 'application/pdf'; 176 } 177 elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-') 178 { 179 return 'application/postscript'; 180 } 181 elseif (substr($this->file->body, 0, 6) === 'GIF87a' 182 || substr($this->file->body, 0, 6) === 'GIF89a') 183 { 184 return 'image/gif'; 185 } 186 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") 187 { 188 return 'image/png'; 189 } 190 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") 191 { 192 return 'image/jpeg'; 193 } 194 elseif (substr($this->file->body, 0, 2) === "\x42\x4D") 195 { 196 return 'image/bmp'; 197 } 198 elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00") 199 { 200 return 'image/vnd.microsoft.icon'; 201 } 202 203 return $this->text_or_binary(); 204 } 205 206 /** 207 * Sniff images 208 * 209 * @return string Actual Content-Type 210 */ 211 public function image() 212 { 213 if (substr($this->file->body, 0, 6) === 'GIF87a' 214 || substr($this->file->body, 0, 6) === 'GIF89a') 215 { 216 return 'image/gif'; 217 } 218 elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") 219 { 220 return 'image/png'; 221 } 222 elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") 223 { 224 return 'image/jpeg'; 225 } 226 elseif (substr($this->file->body, 0, 2) === "\x42\x4D") 227 { 228 return 'image/bmp'; 229 } 230 elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00") 231 { 232 return 'image/vnd.microsoft.icon'; 233 } 234 235 return false; 236 } 237 238 /** 239 * Sniff HTML 240 * 241 * @return string Actual Content-Type 242 */ 243 public function feed_or_html() 244 { 245 $len = strlen($this->file->body); 246 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20\xEF\xBB\xBF"); 247 248 while ($pos < $len) 249 { 250 switch ($this->file->body[$pos]) 251 { 252 case "\x09": 253 case "\x0A": 254 case "\x0D": 255 case "\x20": 256 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos); 257 continue 2; 258 259 case '<': 260 $pos++; 261 break; 262 263 default: 264 return 'text/html'; 265 } 266 267 if (substr($this->file->body, $pos, 3) === '!--') 268 { 269 $pos += 3; 270 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false) 271 { 272 $pos += 3; 273 } 274 else 275 { 276 return 'text/html'; 277 } 278 } 279 elseif (substr($this->file->body, $pos, 1) === '!') 280 { 281 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false) 282 { 283 $pos++; 284 } 285 else 286 { 287 return 'text/html'; 288 } 289 } 290 elseif (substr($this->file->body, $pos, 1) === '?') 291 { 292 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false) 293 { 294 $pos += 2; 295 } 296 else 297 { 298 return 'text/html'; 299 } 300 } 301 elseif (substr($this->file->body, $pos, 3) === 'rss' 302 || substr($this->file->body, $pos, 7) === 'rdf:RDF') 303 { 304 return 'application/rss+xml'; 305 } 306 elseif (substr($this->file->body, $pos, 4) === 'feed') 307 { 308 return 'application/atom+xml'; 309 } 310 else 311 { 312 return 'text/html'; 313 } 314 } 315 316 return 'text/html'; 317 } 63 /** 64 * File object 65 * 66 * @var \SimplePie\File 67 */ 68 public $file; 69 70 /** 71 * Create an instance of the class with the input file 72 * 73 * @param Sniffer $file Input file 74 */ 75 public function __construct($file) 76 { 77 $this->file = $file; 78 } 79 80 /** 81 * Get the Content-Type of the specified file 82 * 83 * @return string Actual Content-Type 84 */ 85 public function get_type() 86 { 87 if (isset($this->file->headers['content-type'])) { 88 if (!isset($this->file->headers['content-encoding']) 89 && ($this->file->headers['content-type'] === 'text/plain' 90 || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1' 91 || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1' 92 || $this->file->headers['content-type'] === 'text/plain; charset=UTF-8')) { 93 return $this->text_or_binary(); 94 } 95 96 if (($pos = strpos($this->file->headers['content-type'], ';')) !== false) { 97 $official = substr($this->file->headers['content-type'], 0, $pos); 98 } else { 99 $official = $this->file->headers['content-type']; 100 } 101 $official = trim(strtolower($official)); 102 103 if ($official === 'unknown/unknown' 104 || $official === 'application/unknown') { 105 return $this->unknown(); 106 } elseif (substr($official, -4) === '+xml' 107 || $official === 'text/xml' 108 || $official === 'application/xml') { 109 return $official; 110 } elseif (substr($official, 0, 6) === 'image/') { 111 if ($return = $this->image()) { 112 return $return; 113 } 114 115 return $official; 116 } elseif ($official === 'text/html') { 117 return $this->feed_or_html(); 118 } 119 120 return $official; 121 } 122 123 return $this->unknown(); 124 } 125 126 /** 127 * Sniff text or binary 128 * 129 * @return string Actual Content-Type 130 */ 131 public function text_or_binary() 132 { 133 if (substr($this->file->body, 0, 2) === "\xFE\xFF" 134 || substr($this->file->body, 0, 2) === "\xFF\xFE" 135 || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF" 136 || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF") { 137 return 'text/plain'; 138 } elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body)) { 139 return 'application/octet-stream'; 140 } 141 142 return 'text/plain'; 143 } 144 145 /** 146 * Sniff unknown 147 * 148 * @return string Actual Content-Type 149 */ 150 public function unknown() 151 { 152 $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20"); 153 if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html' 154 || strtolower(substr($this->file->body, $ws, 5)) === '<html' 155 || strtolower(substr($this->file->body, $ws, 7)) === '<script') { 156 return 'text/html'; 157 } elseif (substr($this->file->body, 0, 5) === '%PDF-') { 158 return 'application/pdf'; 159 } elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-') { 160 return 'application/postscript'; 161 } elseif (substr($this->file->body, 0, 6) === 'GIF87a' 162 || substr($this->file->body, 0, 6) === 'GIF89a') { 163 return 'image/gif'; 164 } elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") { 165 return 'image/png'; 166 } elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") { 167 return 'image/jpeg'; 168 } elseif (substr($this->file->body, 0, 2) === "\x42\x4D") { 169 return 'image/bmp'; 170 } elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00") { 171 return 'image/vnd.microsoft.icon'; 172 } 173 174 return $this->text_or_binary(); 175 } 176 177 /** 178 * Sniff images 179 * 180 * @return string Actual Content-Type 181 */ 182 public function image() 183 { 184 if (substr($this->file->body, 0, 6) === 'GIF87a' 185 || substr($this->file->body, 0, 6) === 'GIF89a') { 186 return 'image/gif'; 187 } elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A") { 188 return 'image/png'; 189 } elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF") { 190 return 'image/jpeg'; 191 } elseif (substr($this->file->body, 0, 2) === "\x42\x4D") { 192 return 'image/bmp'; 193 } elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00") { 194 return 'image/vnd.microsoft.icon'; 195 } 196 197 return false; 198 } 199 200 /** 201 * Sniff HTML 202 * 203 * @return string Actual Content-Type 204 */ 205 public function feed_or_html() 206 { 207 $len = strlen($this->file->body); 208 $pos = strspn($this->file->body, "\x09\x0A\x0D\x20\xEF\xBB\xBF"); 209 210 while ($pos < $len) { 211 switch ($this->file->body[$pos]) { 212 case "\x09": 213 case "\x0A": 214 case "\x0D": 215 case "\x20": 216 $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos); 217 continue 2; 218 219 case '<': 220 $pos++; 221 break; 222 223 default: 224 return 'text/html'; 225 } 226 227 if (substr($this->file->body, $pos, 3) === '!--') { 228 $pos += 3; 229 if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false) { 230 $pos += 3; 231 } else { 232 return 'text/html'; 233 } 234 } elseif (substr($this->file->body, $pos, 1) === '!') { 235 if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false) { 236 $pos++; 237 } else { 238 return 'text/html'; 239 } 240 } elseif (substr($this->file->body, $pos, 1) === '?') { 241 if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false) { 242 $pos += 2; 243 } else { 244 return 'text/html'; 245 } 246 } elseif (substr($this->file->body, $pos, 3) === 'rss' 247 || substr($this->file->body, $pos, 7) === 'rdf:RDF') { 248 return 'application/rss+xml'; 249 } elseif (substr($this->file->body, $pos, 4) === 'feed') { 250 return 'application/atom+xml'; 251 } else { 252 return 'text/html'; 253 } 254 } 255 256 return 'text/html'; 257 } 318 258 } 259 260 class_alias('SimplePie\Content\Type\Sniffer', 'SimplePie_Content_Type_Sniffer');
Note: See TracChangeset
for help on using the changeset viewer.