PageRenderTime 57ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/var/Typecho/Common.php

https://github.com/wangqin4377/typecho
PHP | 1376 lines | 1101 code | 65 blank | 210 comment | 87 complexity | 01248e1a8a8b7032f9af34ec819a4c93 MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. * API方法,Typecho命名空间
  4. *
  5. * @category typecho
  6. * @package Common
  7. * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
  8. * @license GNU General Public License 2.0
  9. * @version $Id$
  10. */
  11. define('__TYPECHO_MB_SUPPORTED__', function_exists('mb_get_info'));
  12. /**
  13. * Typecho公用方法
  14. *
  15. * @category typecho
  16. * @package Common
  17. * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
  18. * @license GNU General Public License 2.0
  19. */
  20. class Typecho_Common
  21. {
  22. /** 程序版本 */
  23. const VERSION = '0.9/14.3.14';
  24. /**
  25. * 锁定的代码块
  26. *
  27. * @access private
  28. * @var array
  29. */
  30. private static $_lockedBlocks = array('<p></p>' => '');
  31. /**
  32. * 允许的属性
  33. *
  34. * @access private
  35. * @var array
  36. */
  37. private static $_allowableAttributes = array();
  38. /**
  39. * 默认编码
  40. *
  41. * @access public
  42. * @var string
  43. */
  44. public static $charset = 'UTF-8';
  45. /**
  46. * 异常处理类
  47. *
  48. * @access public
  49. * @var string
  50. */
  51. public static $exceptionHandle;
  52. /**
  53. * 锁定标签回调函数
  54. *
  55. * @access private
  56. * @param array $matches 匹配的值
  57. * @return string
  58. */
  59. public static function __lockHTML(array $matches)
  60. {
  61. $guid = '<code>' . uniqid(time()) . '</code>';
  62. self::$_lockedBlocks[$guid] = $matches[0];
  63. return $guid;
  64. }
  65. /**
  66. * 将url中的非法xss去掉时的数组回调过滤函数
  67. *
  68. * @access private
  69. * @param string $string 需要过滤的字符串
  70. * @return string
  71. */
  72. public static function __removeUrlXss($string)
  73. {
  74. $string = str_replace(array('%0d', '%0a'), '', strip_tags($string));
  75. return preg_replace(array(
  76. "/\(\s*(\"|')/i", //函数开头
  77. "/(\"|')\s*\)/i", //函数结尾
  78. ), '', $string);
  79. }
  80. /**
  81. * 检查是否为安全路径
  82. *
  83. * @access public
  84. * @param string $path 检查是否为安全路径
  85. * @return boolean
  86. */
  87. public static function __safePath($path)
  88. {
  89. $safePath = rtrim(__TYPECHO_ROOT_DIR__, '/');
  90. return 0 === strpos($path, $safePath);
  91. }
  92. /**
  93. * __filterAttrs
  94. *
  95. * @param mixed $matches
  96. * @static
  97. * @access public
  98. * @return bool
  99. */
  100. public static function __filterAttrs($matches)
  101. {
  102. if (!isset($matches[2])) {
  103. return $matches[0];
  104. }
  105. $str = trim($matches[2]);
  106. if (empty($str)) {
  107. return $matches[0];
  108. }
  109. $attrs = self::__parseAttrs($str);
  110. $parsedAttrs = array();
  111. $tag = strtolower($matches[1]);
  112. foreach ($attrs as $key => $val) {
  113. if (in_array($key, self::$_allowableAttributes[$tag])) {
  114. $parsedAttrs[] = " {$key}" . (empty($val) ? '' : "={$val}");
  115. }
  116. }
  117. return '<' . $tag . implode('', $parsedAttrs) . '>';
  118. }
  119. /**
  120. * 解析属性
  121. *
  122. * @access public
  123. * @param string $attrs 属性字符串
  124. * @return array
  125. */
  126. public static function __parseAttrs($attrs)
  127. {
  128. $attrs = trim($attrs);
  129. $len = strlen($attrs);
  130. $pos = -1;
  131. $result = array();
  132. $quote = '';
  133. $key = '';
  134. $value = '';
  135. for ($i = 0; $i < $len; $i ++) {
  136. if ('=' != $attrs[$i] && !ctype_space($attrs[$i]) && -1 == $pos) {
  137. $key .= $attrs[$i];
  138. /** 最后一个 */
  139. if ($i == $len - 1) {
  140. if ('' != ($key = trim($key))) {
  141. $result[$key] = '';
  142. $key = '';
  143. $value = '';
  144. }
  145. }
  146. } else if (ctype_space($attrs[$i]) && -1 == $pos) {
  147. $pos = -2;
  148. } else if ('=' == $attrs[$i] && 0 > $pos) {
  149. $pos = 0;
  150. } else if (('"' == $attrs[$i] || "'" == $attrs[$i]) && 0 == $pos) {
  151. $quote = $attrs[$i];
  152. $value .= $attrs[$i];
  153. $pos = 1;
  154. } else if ($quote != $attrs[$i] && 1 == $pos) {
  155. $value .= $attrs[$i];
  156. } else if ($quote == $attrs[$i] && 1 == $pos) {
  157. $pos = -1;
  158. $value .= $attrs[$i];
  159. $result[trim($key)] = $value;
  160. $key = '';
  161. $value = '';
  162. } else if ('=' != $attrs[$i] && !ctype_space($attrs[$i]) && -2 == $pos) {
  163. if ('' != ($key = trim($key))) {
  164. $result[$key] = '';
  165. }
  166. $key = '';
  167. $value = '';
  168. $pos = -1;
  169. $key .= $attrs[$i];
  170. }
  171. }
  172. return $result;
  173. }
  174. /**
  175. * 自动载入类
  176. *
  177. * @param $className
  178. */
  179. public static function __autoLoad($className)
  180. {
  181. @include_once str_replace(array('\\', '_'), '/', $className) . '.php';
  182. }
  183. /**
  184. * 程序初始化方法
  185. *
  186. * @access public
  187. * @return void
  188. */
  189. public static function init()
  190. {
  191. /** 设置自动载入函数 */
  192. if (function_exists('spl_autoload_register')) {
  193. spl_autoload_register(array('Typecho_Common', '__autoLoad'));
  194. } else {
  195. function __autoLoad($className) {
  196. Typecho_Common::__autoLoad($className);
  197. }
  198. }
  199. /** 兼容php6 */
  200. if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
  201. $_GET = self::stripslashesDeep($_GET);
  202. $_POST = self::stripslashesDeep($_POST);
  203. $_COOKIE = self::stripslashesDeep($_COOKIE);
  204. reset($_GET);
  205. reset($_POST);
  206. reset($_COOKIE);
  207. }
  208. /** 设置异常截获函数 */
  209. set_exception_handler(array('Typecho_Common', 'exceptionHandle'));
  210. }
  211. /**
  212. * 异常截获函数
  213. *
  214. * @access public
  215. * @param Exception $exception 截获的异常
  216. * @return void
  217. */
  218. public static function exceptionHandle(Exception $exception)
  219. {
  220. @ob_end_clean();
  221. if (defined('__TYPECHO_DEBUG__')) {
  222. echo nl2br($exception->__toString());
  223. } else {
  224. if (404 == $exception->getCode() && !empty(self::$exceptionHandle)) {
  225. $handleClass = self::$exceptionHandle;
  226. new $handleClass($exception);
  227. } else {
  228. self::error($exception);
  229. }
  230. }
  231. exit;
  232. }
  233. /**
  234. * 输出错误页面
  235. *
  236. * @access public
  237. * @param mixed $exception 错误信息
  238. * @return void
  239. */
  240. public static function error($exception)
  241. {
  242. $isException = is_object($exception);
  243. $message = '';
  244. if ($isException) {
  245. $code = $exception->getCode();
  246. $message = $exception->getMessage();
  247. } else {
  248. $code = $exception;
  249. }
  250. $charset = self::$charset;
  251. if ($isException && $exception instanceof Typecho_Db_Exception) {
  252. $code = 500;
  253. @error_log($message);
  254. //覆盖原始错误信息
  255. $message = 'Database Server Error';
  256. if ($exception instanceof Typecho_Db_Adapter_Exception) {
  257. $code = 503;
  258. $message = 'Error establishing a database connection';
  259. } else if ($exception instanceof Typecho_Db_Query_Exception) {
  260. $message = 'Database Query Error';
  261. }
  262. } else {
  263. switch ($code) {
  264. case 500:
  265. $message = 'Server Error';
  266. break;
  267. case 404:
  268. $message = 'Page Not Found';
  269. break;
  270. default:
  271. $code = 'Error';
  272. break;
  273. }
  274. }
  275. /** 设置http code */
  276. if (is_numeric($code) && $code > 200) {
  277. Typecho_Response::setStatus($code);
  278. }
  279. $message = nl2br($message);
  280. if (defined('__TYPECHO_EXCEPTION_FILE__')) {
  281. require_once __TYPECHO_EXCEPTION_FILE__;
  282. } else {
  283. echo
  284. <<<EOF
  285. <!DOCTYPE html>
  286. <html lang="en">
  287. <head>
  288. <meta charset="{$charset}">
  289. <title>{$code}</title>
  290. <style>
  291. html {
  292. padding: 50px 10px;
  293. font-size: 20px;
  294. line-height: 1.4;
  295. color: #666;
  296. background: #F6F6F3;
  297. -webkit-text-size-adjust: 100%;
  298. -ms-text-size-adjust: 100%;
  299. }
  300. html,
  301. input { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
  302. body {
  303. max-width: 500px;
  304. _width: 500px;
  305. padding: 30px 20px 50px;
  306. margin: 0 auto;
  307. background: #FFF;
  308. }
  309. h1 {
  310. font-size: 50px;
  311. text-align: center;
  312. }
  313. h1 span { color: #bbb; }
  314. ul {
  315. padding: 0 0 0 40px;
  316. }
  317. .container {
  318. max-width: 380px;
  319. _width: 380px;
  320. margin: 0 auto;
  321. }
  322. </style>
  323. </head>
  324. <body>
  325. <div class="container">
  326. <h1>{$code}</h1>
  327. {$message}
  328. </div>
  329. </body>
  330. </html>
  331. EOF;
  332. }
  333. exit;
  334. }
  335. /**
  336. * 判断类是否能被加载
  337. * 此函数会遍历所有的include目录, 所以会有一定的性能消耗, 但是不会很大
  338. * 可是我们依然建议你在必须检测一个类能否被加载时使用它, 它通常表现为以下两种情况
  339. * 1. 当需要被加载的类不存在时, 系统不会停止运行 (如果你不判断, 系统会因抛出严重错误而停止)
  340. * 2. 你需要知道哪些类无法被加载, 以提示使用者
  341. * 除了以上情况, 你无需关注那些类无法被加载, 因为当它们不存在时系统会自动停止并报错
  342. *
  343. * @access public
  344. * @param string $className 类名
  345. * @param string $path 指定的路径名称
  346. * @return boolean
  347. */
  348. public static function isAvailableClass($className, $path = NULL)
  349. {
  350. /** 获取所有include目录 */
  351. //增加安全目录检测 fix issue 106
  352. $dirs = array_map('realpath', array_filter(explode(PATH_SEPARATOR, get_include_path()),
  353. array('Typecho_Common', '__safePath')));
  354. $file = str_replace('_', '/', $className) . '.php';
  355. if (!empty($path)) {
  356. $path = realpath($path);
  357. if (in_array($path, $dirs)) {
  358. $dirs = array($path);
  359. } else {
  360. return false;
  361. }
  362. }
  363. foreach ($dirs as $dir) {
  364. if (!empty($dir)) {
  365. if (file_exists($dir . '/' . $file)) {
  366. return true;
  367. }
  368. }
  369. }
  370. return false;
  371. }
  372. /**
  373. * 检测是否在app engine上运行,屏蔽某些功能
  374. *
  375. * @static
  376. * @access public
  377. * @return boolean
  378. */
  379. public static function isAppEngine()
  380. {
  381. return !empty($_SERVER['HTTP_APPNAME']) // SAE
  382. || !!getenv('HTTP_BAE_ENV_APPID') // BAE
  383. || !!getenv('HTTP_BAE_LOGID') // BAE 3.0
  384. || (ini_get('acl.app_id') && class_exists('Alibaba')) // ACE
  385. || (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'],'Google App Engine') !== false) // GAE
  386. ;
  387. }
  388. /**
  389. * 递归去掉数组反斜线
  390. *
  391. * @access public
  392. * @param mixed $value
  393. * @return mixed
  394. */
  395. public static function stripslashesDeep($value)
  396. {
  397. return is_array($value) ? array_map(array('Typecho_Common', 'stripslashesDeep'), $value) : stripslashes($value);
  398. }
  399. /**
  400. * 抽取多维数组的某个元素,组成一个新数组,使这个数组变成一个扁平数组
  401. * 使用方法:
  402. * <code>
  403. * <?php
  404. * $fruit = array(array('apple' => 2, 'banana' => 3), array('apple' => 10, 'banana' => 12));
  405. * $banana = Typecho_Common::arrayFlatten($fruit, 'banana');
  406. * print_r($banana);
  407. * //outputs: array(0 => 3, 1 => 12);
  408. * ?>
  409. * </code>
  410. *
  411. * @access public
  412. * @param array $value 被处理的数组
  413. * @param string $key 需要抽取的键值
  414. * @return array
  415. */
  416. public static function arrayFlatten(array $value, $key)
  417. {
  418. $result = array();
  419. if ($value) {
  420. foreach ($value as $inval) {
  421. if (is_array($inval) && isset($inval[$key])) {
  422. $result[] = $inval[$key];
  423. } else {
  424. break;
  425. }
  426. }
  427. }
  428. return $result;
  429. }
  430. /**
  431. * 根据parse_url的结果重新组合url
  432. *
  433. * @access public
  434. * @param array $params 解析后的参数
  435. * @return string
  436. */
  437. public static function buildUrl($params)
  438. {
  439. return (isset($params['scheme']) ? $params['scheme'] . '://' : NULL)
  440. . (isset($params['user']) ? $params['user'] . (isset($params['pass']) ? ':' . $params['pass'] : NULL) . '@' : NULL)
  441. . (isset($params['host']) ? $params['host'] : NULL)
  442. . (isset($params['port']) ? ':' . $params['port'] : NULL)
  443. . (isset($params['path']) ? $params['path'] : NULL)
  444. . (isset($params['query']) ? '?' . $params['query'] : NULL)
  445. . (isset($params['fragment']) ? '#' . $params['fragment'] : NULL);
  446. }
  447. /**
  448. * 根据count数目来输出字符
  449. * <code>
  450. * echo splitByCount(20, 10, 20, 30, 40, 50);
  451. * </code>
  452. *
  453. * @access public
  454. * @param int $count
  455. * @return string
  456. */
  457. public static function splitByCount($count)
  458. {
  459. $sizes = func_get_args();
  460. array_shift($sizes);
  461. foreach ($sizes as $size) {
  462. if ($count < $size) {
  463. return $size;
  464. }
  465. }
  466. return 0;
  467. }
  468. /**
  469. * 自闭合html修复函数
  470. * 使用方法:
  471. * <code>
  472. * $input = '这是一段被截断的html文本<a href="#"';
  473. * echo Typecho_Common::fixHtml($input);
  474. * //output: 这是一段被截断的html文本
  475. * </code>
  476. *
  477. * @access public
  478. * @param string $string 需要修复处理的字符串
  479. * @return string
  480. */
  481. public static function fixHtml($string)
  482. {
  483. //关闭自闭合标签
  484. $startPos = strrpos($string, "<");
  485. if (false == $startPos) {
  486. return $string;
  487. }
  488. $trimString = substr($string, $startPos);
  489. if (false === strpos($trimString, ">")) {
  490. $string = substr($string, 0, $startPos);
  491. }
  492. //非自闭合html标签列表
  493. preg_match_all("/<([_0-9a-zA-Z-\:]+)\s*([^>]*)>/is", $string, $startTags);
  494. preg_match_all("/<\/([_0-9a-zA-Z-\:]+)>/is", $string, $closeTags);
  495. if (!empty($startTags[1]) && is_array($startTags[1])) {
  496. krsort($startTags[1]);
  497. $closeTagsIsArray = is_array($closeTags[1]);
  498. foreach ($startTags[1] as $key => $tag) {
  499. $attrLength = strlen($startTags[2][$key]);
  500. if ($attrLength > 0 && "/" == trim($startTags[2][$key][$attrLength - 1])) {
  501. continue;
  502. }
  503. if (!empty($closeTags[1]) && $closeTagsIsArray) {
  504. if (false !== ($index = array_search($tag, $closeTags[1]))) {
  505. unset($closeTags[1][$index]);
  506. continue;
  507. }
  508. }
  509. $string .= "</{$tag}>";
  510. }
  511. }
  512. return preg_replace("/\<br\s*\/\>\s*\<\/p\>/is", '</p>', $string);
  513. }
  514. /**
  515. * 去掉字符串中的html标签
  516. * 使用方法:
  517. * <code>
  518. * $input = '<a href="http://test/test.php" title="example">hello</a>';
  519. * $output = Typecho_Common::stripTags($input, <a href="">);
  520. * echo $output;
  521. * //display: '<a href="http://test/test.php">hello</a>'
  522. * </code>
  523. *
  524. * @access public
  525. * @param string $html 需要处理的字符串
  526. * @param string $allowableTags 需要忽略的html标签
  527. * @return string
  528. */
  529. public static function stripTags($html, $allowableTags = NULL)
  530. {
  531. $normalizeTags = '';
  532. $allowableAttributes = array();
  533. if (!empty($allowableTags) && preg_match_all("/\<([_a-z0-9-]+)([^>]*)\>/is", $allowableTags, $tags)) {
  534. $normalizeTags = '<' . implode('><', array_map('strtolower', $tags[1])) . '>';
  535. $attributes = array_map('trim', $tags[2]);
  536. foreach ($attributes as $key => $val) {
  537. $allowableAttributes[strtolower($tags[1][$key])] =
  538. array_map('strtolower', array_keys(self::__parseAttrs($val)));
  539. }
  540. }
  541. self::$_allowableAttributes = $allowableAttributes;
  542. $html = strip_tags($html, $normalizeTags);
  543. $html = preg_replace_callback("/<([_a-z0-9-]+)(\s+[^>]+)?>/is",
  544. array('Typecho_Common', '__filterAttrs'), $html);
  545. return $html;
  546. }
  547. /**
  548. * 过滤用于搜索的字符串
  549. *
  550. * @access public
  551. * @param string $query 搜索字符串
  552. * @return string
  553. */
  554. public static function filterSearchQuery($query)
  555. {
  556. return str_replace('-', ' ', self::slugName($query));
  557. }
  558. /**
  559. * 将url中的非法字符串
  560. *
  561. * @param string $url 需要过滤的url
  562. * @return string
  563. */
  564. public static function safeUrl($url)
  565. {
  566. //~ 针对location的xss过滤, 因为其特殊性无法使用removeXSS函数
  567. //~ fix issue 66
  568. $params = parse_url(str_replace(array("\r", "\n", "\t", ' '), '', $url));
  569. /** 禁止非法的协议跳转 */
  570. if (isset($params['scheme'])) {
  571. if (!in_array($params['scheme'], array('http', 'https'))) {
  572. return '/';
  573. }
  574. }
  575. /** 过滤解析串 */
  576. $params = array_map(array('Typecho_Common', '__removeUrlXss'), $params);
  577. return self::buildUrl($params);
  578. }
  579. /**
  580. * 处理XSS跨站攻击的过滤函数
  581. *
  582. * @author kallahar@kallahar.com
  583. * @link http://kallahar.com/smallprojects/php_xss_filter_function.php
  584. * @access public
  585. * @param string $val 需要处理的字符串
  586. * @return string
  587. */
  588. public static function removeXSS($val)
  589. {
  590. // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
  591. // this prevents some character re-spacing such as <java\0script>
  592. // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
  593. $val = preg_replace('/([\x00-\x08]|[\x0b-\x0c]|[\x0e-\x19])/', '', $val);
  594. // straight replacements, the user should never need these since they're normal characters
  595. // this prevents like <IMG SRC=&#X40&#X61&#X76&#X61&#X73&#X63&#X72&#X69&#X70&#X74&#X3A&#X61&#X6C&#X65&#X72&#X74&#X28&#X27&#X58&#X53&#X53&#X27&#X29>
  596. $search = 'abcdefghijklmnopqrstuvwxyz';
  597. $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  598. $search .= '1234567890!@#$%^&*()';
  599. $search .= '~`";:?+/={}[]-_|\'\\';
  600. for ($i = 0; $i < strlen($search); $i++) {
  601. // ;? matches the ;, which is optional
  602. // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
  603. // &#x0040 @ search for the hex values
  604. $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
  605. // &#00064 @ 0{0,7} matches '0' zero to seven times
  606. $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
  607. }
  608. // now the only remaining whitespace attacks are \t, \n, and \r
  609. $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
  610. $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
  611. $ra = array_merge($ra1, $ra2);
  612. $found = true; // keep replacing as long as the previous round replaced something
  613. while ($found == true) {
  614. $val_before = $val;
  615. for ($i = 0; $i < sizeof($ra); $i++) {
  616. $pattern = '/';
  617. for ($j = 0; $j < strlen($ra[$i]); $j++) {
  618. if ($j > 0) {
  619. $pattern .= '(';
  620. $pattern .= '(&#[xX]0{0,8}([9ab]);)';
  621. $pattern .= '|';
  622. $pattern .= '|(&#0{0,8}([9|10|13]);)';
  623. $pattern .= ')*';
  624. }
  625. $pattern .= $ra[$i][$j];
  626. }
  627. $pattern .= '/i';
  628. $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
  629. $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
  630. if ($val_before == $val) {
  631. // no replacements were made, so exit the loop
  632. $found = false;
  633. }
  634. }
  635. }
  636. return $val;
  637. }
  638. /**
  639. * 宽字符串截字函数
  640. *
  641. * @access public
  642. * @param string $str 需要截取的字符串
  643. * @param integer $start 开始截取的位置
  644. * @param integer $length 需要截取的长度
  645. * @param string $trim 截取后的截断标示符
  646. * @return string
  647. */
  648. public static function subStr($str, $start, $length, $trim = "...")
  649. {
  650. if (!strlen($str)) {
  651. return '';
  652. }
  653. $iLength = self::strLen($str) - $start;
  654. $tLength = $length < $iLength ? ($length - self::strLen($trim)) : $length;
  655. if (__TYPECHO_MB_SUPPORTED__) {
  656. $str = mb_substr($str, $start, $tLength, self::$charset);
  657. } else {
  658. if ('UTF-8' == strtoupper(self::$charset)) {
  659. if (preg_match_all("/./u", $str, $matches)) {
  660. $str = implode('', array_slice($matches[0], $start, $tLength));
  661. }
  662. } else {
  663. $str = substr($str, $start, $tLength);
  664. }
  665. }
  666. return $length < $iLength ? ($str . $trim) : $str;
  667. }
  668. /**
  669. * 获取宽字符串长度函数
  670. *
  671. * @access public
  672. * @param string $str 需要获取长度的字符串
  673. * @return integer
  674. */
  675. public static function strLen($str)
  676. {
  677. if (__TYPECHO_MB_SUPPORTED__) {
  678. return mb_strlen($str, self::$charset);
  679. } else {
  680. return 'UTF-8' == strtoupper(self::$charset)
  681. ? strlen(utf8_decode($str)) : strlen($str);
  682. }
  683. }
  684. /**
  685. * 检查是否为合法的编码数据
  686. *
  687. * @param string|array $str
  688. * @return boolean
  689. */
  690. public static function checkStrEncoding($str)
  691. {
  692. if (is_array($str)) {
  693. return array_map(array('Typecho_Common', 'checkStrEncoding'), $str);
  694. }
  695. if (__TYPECHO_MB_SUPPORTED__) {
  696. return mb_check_encoding($str, self::$charset);
  697. } else {
  698. // just support utf-8
  699. return preg_match('//u', $str);
  700. }
  701. }
  702. /**
  703. * 生成缩略名
  704. *
  705. * @access public
  706. * @param string $str 需要生成缩略名的字符串
  707. * @param string $default 默认的缩略名
  708. * @param integer $maxLength 缩略名最大长度
  709. * @return string
  710. */
  711. public static function slugName($str, $default = NULL, $maxLength = 128)
  712. {
  713. $str = trim($str);
  714. if (!strlen($str)) {
  715. return $default;
  716. }
  717. if (__TYPECHO_MB_SUPPORTED__) {
  718. mb_regex_encoding(self::$charset);
  719. mb_ereg_search_init($str, "[\w" . preg_quote('_-') . "]+");
  720. $result = mb_ereg_search();
  721. $return = '';
  722. if ($result) {
  723. $regs = mb_ereg_search_getregs();
  724. $pos = 0;
  725. do {
  726. $return .= ($pos > 0 ? '-' : '') . $regs[0];
  727. $pos ++;
  728. } while ($regs = mb_ereg_search_regs());
  729. }
  730. $str = $return;
  731. } else if ('UTF-8' == strtoupper(self::$charset)) {
  732. if (preg_match_all("/[\w" . preg_quote('_-') . "]+/u", $str, $matches)) {
  733. $str = implode('-', $matches[0]);
  734. }
  735. } else {
  736. $str = str_replace(array("'", ":", "\\", "/", '"'), "", $str);
  737. $str = str_replace(array("+", ",", ' ', ',', ' ', ".", "?", "=", "&", "!", "<", ">", "(", ")", "[", "]", "{", "}"), "-", $str);
  738. }
  739. $str = trim($str, '-_');
  740. $str = !strlen($str) ? $default : $str;
  741. return substr($str, 0, $maxLength);
  742. }
  743. /**
  744. * 去掉html中的分段
  745. *
  746. * @access public
  747. * @param string $html 输入串
  748. * @return string
  749. */
  750. public static function removeParagraph($html)
  751. {
  752. /** 锁定标签 */
  753. $html = self::lockHTML($html);
  754. $html = str_replace(array("\r", "\n"), '', $html);
  755. $html = trim(preg_replace(
  756. array("/\s*<p>(.*?)<\/p>\s*/is", "/\s*<br\s*\/>\s*/is",
  757. "/\s*<(div|blockquote|pre|code|script|table|fieldset|ol|ul|dl|h[1-6])([^>]*)>/is",
  758. "/<\/(div|blockquote|pre|code|script|table|fieldset|ol|ul|dl|h[1-6])>\s*/is", "/\s*<\!--more-->\s*/is"),
  759. array("\n\\1\n", "\n", "\n\n<\\1\\2>", "</\\1>\n\n", "\n\n<!--more-->\n\n"),
  760. $html));
  761. return trim(self::releaseHTML($html));
  762. }
  763. /**
  764. * 锁定标签
  765. *
  766. * @access public
  767. * @param string $html 输入串
  768. * @return string
  769. */
  770. public static function lockHTML($html)
  771. {
  772. return preg_replace_callback("/<(code|pre|script)[^>]*>.*?<\/\\1>/is", array('Typecho_Common', '__lockHTML'), $html);
  773. }
  774. /**
  775. * 释放标签
  776. *
  777. * @access public
  778. * @param string $html 输入串
  779. * @return string
  780. */
  781. public static function releaseHTML($html)
  782. {
  783. $html = trim(str_replace(array_keys(self::$_lockedBlocks), array_values(self::$_lockedBlocks), $html));
  784. self::$_lockedBlocks = array('<p></p>' => '');
  785. return $html;
  786. }
  787. /**
  788. * 文本分段函数
  789. *
  790. * @param string $string 需要分段的字符串
  791. * @return string
  792. */
  793. public static function cutParagraph($string)
  794. {
  795. static $loaded;
  796. if (!$loaded) {
  797. $loaded = true;
  798. }
  799. return Typecho_Common_Paragraph::process($string);
  800. }
  801. /**
  802. * 生成随机字符串
  803. *
  804. * @access public
  805. * @param integer $length 字符串长度
  806. * @param boolean $specialChars 是否有特殊字符
  807. * @return string
  808. */
  809. public static function randString($length, $specialChars = false)
  810. {
  811. $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  812. if ($specialChars) {
  813. $chars .= '!@#$%^&*()';
  814. }
  815. $result = '';
  816. $max = strlen($chars) - 1;
  817. for ($i = 0; $i < $length; $i++) {
  818. $result .= $chars[rand(0, $max)];
  819. }
  820. return $result;
  821. }
  822. /**
  823. * 对字符串进行hash加密
  824. *
  825. * @access public
  826. * @param string $string 需要hash的字符串
  827. * @param string $salt 扰码
  828. * @return string
  829. */
  830. public static function hash($string, $salt = NULL)
  831. {
  832. /** 生成随机字符串 */
  833. $salt = empty($salt) ? self::randString(9) : $salt;
  834. $length = strlen($string);
  835. $hash = '';
  836. $last = ord($string[$length - 1]);
  837. $pos = 0;
  838. /** 判断扰码长度 */
  839. if (strlen($salt) != 9) {
  840. /** 如果不是9直接返回 */
  841. return;
  842. }
  843. while ($pos < $length) {
  844. $asc = ord($string[$pos]);
  845. $last = ($last * ord($salt[($last % $asc) % 9]) + $asc) % 95 + 32;
  846. $hash .= chr($last);
  847. $pos ++;
  848. }
  849. return '$T$' . $salt . md5($hash);
  850. }
  851. /**
  852. * 判断hash值是否相等
  853. *
  854. * @access public
  855. * @param string $from 源字符串
  856. * @param string $to 目标字符串
  857. * @return boolean
  858. */
  859. public static function hashValidate($from, $to)
  860. {
  861. if ('$T$' == substr($to, 0, 3)) {
  862. $salt = substr($to, 3, 9);
  863. return self::hash($from, $salt) === $to;
  864. } else {
  865. return md5($from) === $to;
  866. }
  867. }
  868. /**
  869. * 将路径转化为链接
  870. *
  871. * @access public
  872. * @param string $path 路径
  873. * @param string $prefix 前缀
  874. * @return string
  875. */
  876. public static function url($path, $prefix)
  877. {
  878. $path = (0 === strpos($path, './')) ? substr($path, 2) : $path;
  879. return rtrim($prefix, '/') . '/' . str_replace('//', '/', ltrim($path, '/'));
  880. }
  881. /**
  882. * 获取图片
  883. *
  884. * @access public
  885. * @param string $fileName 文件名
  886. * @return string
  887. */
  888. public static function mimeContentType($fileName)
  889. {
  890. //改为并列判断
  891. if (function_exists('mime_content_type')) {
  892. return mime_content_type($fileName);
  893. }
  894. if (function_exists('finfo_open')) {
  895. $fInfo = @finfo_open(FILEINFO_MIME);
  896. if (false !== $fInfo) {
  897. $mimeType = finfo_file($fInfo, $fileName);
  898. finfo_close($fInfo);
  899. return $mimeType;
  900. }
  901. }
  902. $mimeTypes = array(
  903. 'ez' => 'application/andrew-inset',
  904. 'csm' => 'application/cu-seeme',
  905. 'cu' => 'application/cu-seeme',
  906. 'tsp' => 'application/dsptype',
  907. 'spl' => 'application/x-futuresplash',
  908. 'hta' => 'application/hta',
  909. 'cpt' => 'image/x-corelphotopaint',
  910. 'hqx' => 'application/mac-binhex40',
  911. 'nb' => 'application/mathematica',
  912. 'mdb' => 'application/msaccess',
  913. 'doc' => 'application/msword',
  914. 'dot' => 'application/msword',
  915. 'bin' => 'application/octet-stream',
  916. 'oda' => 'application/oda',
  917. 'ogg' => 'application/ogg',
  918. 'prf' => 'application/pics-rules',
  919. 'key' => 'application/pgp-keys',
  920. 'pdf' => 'application/pdf',
  921. 'pgp' => 'application/pgp-signature',
  922. 'ps' => 'application/postscript',
  923. 'ai' => 'application/postscript',
  924. 'eps' => 'application/postscript',
  925. 'rss' => 'application/rss+xml',
  926. 'rtf' => 'text/rtf',
  927. 'smi' => 'application/smil',
  928. 'smil' => 'application/smil',
  929. 'wp5' => 'application/wordperfect5.1',
  930. 'xht' => 'application/xhtml+xml',
  931. 'xhtml' => 'application/xhtml+xml',
  932. 'zip' => 'application/zip',
  933. 'cdy' => 'application/vnd.cinderella',
  934. 'mif' => 'application/x-mif',
  935. 'xls' => 'application/vnd.ms-excel',
  936. 'xlb' => 'application/vnd.ms-excel',
  937. 'cat' => 'application/vnd.ms-pki.seccat',
  938. 'stl' => 'application/vnd.ms-pki.stl',
  939. 'ppt' => 'application/vnd.ms-powerpoint',
  940. 'pps' => 'application/vnd.ms-powerpoint',
  941. 'pot' => 'application/vnd.ms-powerpoint',
  942. 'sdc' => 'application/vnd.stardivision.calc',
  943. 'sda' => 'application/vnd.stardivision.draw',
  944. 'sdd' => 'application/vnd.stardivision.impress',
  945. 'sdp' => 'application/vnd.stardivision.impress',
  946. 'smf' => 'application/vnd.stardivision.math',
  947. 'sdw' => 'application/vnd.stardivision.writer',
  948. 'vor' => 'application/vnd.stardivision.writer',
  949. 'sgl' => 'application/vnd.stardivision.writer-global',
  950. 'sxc' => 'application/vnd.sun.xml.calc',
  951. 'stc' => 'application/vnd.sun.xml.calc.template',
  952. 'sxd' => 'application/vnd.sun.xml.draw',
  953. 'std' => 'application/vnd.sun.xml.draw.template',
  954. 'sxi' => 'application/vnd.sun.xml.impress',
  955. 'sti' => 'application/vnd.sun.xml.impress.template',
  956. 'sxm' => 'application/vnd.sun.xml.math',
  957. 'sxw' => 'application/vnd.sun.xml.writer',
  958. 'sxg' => 'application/vnd.sun.xml.writer.global',
  959. 'stw' => 'application/vnd.sun.xml.writer.template',
  960. 'sis' => 'application/vnd.symbian.install',
  961. 'wbxml' => 'application/vnd.wap.wbxml',
  962. 'wmlc' => 'application/vnd.wap.wmlc',
  963. 'wmlsc' => 'application/vnd.wap.wmlscriptc',
  964. 'wk' => 'application/x-123',
  965. 'dmg' => 'application/x-apple-diskimage',
  966. 'bcpio' => 'application/x-bcpio',
  967. 'torrent' => 'application/x-bittorrent',
  968. 'cdf' => 'application/x-cdf',
  969. 'vcd' => 'application/x-cdlink',
  970. 'pgn' => 'application/x-chess-pgn',
  971. 'cpio' => 'application/x-cpio',
  972. 'csh' => 'text/x-csh',
  973. 'deb' => 'application/x-debian-package',
  974. 'dcr' => 'application/x-director',
  975. 'dir' => 'application/x-director',
  976. 'dxr' => 'application/x-director',
  977. 'wad' => 'application/x-doom',
  978. 'dms' => 'application/x-dms',
  979. 'dvi' => 'application/x-dvi',
  980. 'pfa' => 'application/x-font',
  981. 'pfb' => 'application/x-font',
  982. 'gsf' => 'application/x-font',
  983. 'pcf' => 'application/x-font',
  984. 'pcf.Z' => 'application/x-font',
  985. 'gnumeric' => 'application/x-gnumeric',
  986. 'sgf' => 'application/x-go-sgf',
  987. 'gcf' => 'application/x-graphing-calculator',
  988. 'gtar' => 'application/x-gtar',
  989. 'tgz' => 'application/x-gtar',
  990. 'taz' => 'application/x-gtar',
  991. 'gz' => 'application/x-gtar',
  992. 'hdf' => 'application/x-hdf',
  993. 'phtml' => 'application/x-httpd-php',
  994. 'pht' => 'application/x-httpd-php',
  995. 'php' => 'application/x-httpd-php',
  996. 'phps' => 'application/x-httpd-php-source',
  997. 'php3' => 'application/x-httpd-php3',
  998. 'php3p' => 'application/x-httpd-php3-preprocessed',
  999. 'php4' => 'application/x-httpd-php4',
  1000. 'ica' => 'application/x-ica',
  1001. 'ins' => 'application/x-internet-signup',
  1002. 'isp' => 'application/x-internet-signup',
  1003. 'iii' => 'application/x-iphone',
  1004. 'jar' => 'application/x-java-archive',
  1005. 'jnlp' => 'application/x-java-jnlp-file',
  1006. 'ser' => 'application/x-java-serialized-object',
  1007. 'class' => 'application/x-java-vm',
  1008. 'js' => 'application/x-javascript',
  1009. 'chrt' => 'application/x-kchart',
  1010. 'kil' => 'application/x-killustrator',
  1011. 'kpr' => 'application/x-kpresenter',
  1012. 'kpt' => 'application/x-kpresenter',
  1013. 'skp' => 'application/x-koan',
  1014. 'skd' => 'application/x-koan',
  1015. 'skt' => 'application/x-koan',
  1016. 'skm' => 'application/x-koan',
  1017. 'ksp' => 'application/x-kspread',
  1018. 'kwd' => 'application/x-kword',
  1019. 'kwt' => 'application/x-kword',
  1020. 'latex' => 'application/x-latex',
  1021. 'lha' => 'application/x-lha',
  1022. 'lzh' => 'application/x-lzh',
  1023. 'lzx' => 'application/x-lzx',
  1024. 'frm' => 'application/x-maker',
  1025. 'maker' => 'application/x-maker',
  1026. 'frame' => 'application/x-maker',
  1027. 'fm' => 'application/x-maker',
  1028. 'fb' => 'application/x-maker',
  1029. 'book' => 'application/x-maker',
  1030. 'fbdoc' => 'application/x-maker',
  1031. 'wmz' => 'application/x-ms-wmz',
  1032. 'wmd' => 'application/x-ms-wmd',
  1033. 'com' => 'application/x-msdos-program',
  1034. 'exe' => 'application/x-msdos-program',
  1035. 'bat' => 'application/x-msdos-program',
  1036. 'dll' => 'application/x-msdos-program',
  1037. 'msi' => 'application/x-msi',
  1038. 'nc' => 'application/x-netcdf',
  1039. 'pac' => 'application/x-ns-proxy-autoconfig',
  1040. 'nwc' => 'application/x-nwc',
  1041. 'o' => 'application/x-object',
  1042. 'oza' => 'application/x-oz-application',
  1043. 'pl' => 'application/x-perl',
  1044. 'pm' => 'application/x-perl',
  1045. 'p7r' => 'application/x-pkcs7-certreqresp',
  1046. 'crl' => 'application/x-pkcs7-crl',
  1047. 'qtl' => 'application/x-quicktimeplayer',
  1048. 'rpm' => 'audio/x-pn-realaudio-plugin',
  1049. 'shar' => 'application/x-shar',
  1050. 'swf' => 'application/x-shockwave-flash',
  1051. 'swfl' => 'application/x-shockwave-flash',
  1052. 'sh' => 'text/x-sh',
  1053. 'sit' => 'application/x-stuffit',
  1054. 'sv4cpio' => 'application/x-sv4cpio',
  1055. 'sv4crc' => 'application/x-sv4crc',
  1056. 'tar' => 'application/x-tar',
  1057. 'tcl' => 'text/x-tcl',
  1058. 'tex' => 'text/x-tex',
  1059. 'gf' => 'application/x-tex-gf',
  1060. 'pk' => 'application/x-tex-pk',
  1061. 'texinfo' => 'application/x-texinfo',
  1062. 'texi' => 'application/x-texinfo',
  1063. '~' => 'application/x-trash',
  1064. '%' => 'application/x-trash',
  1065. 'bak' => 'application/x-trash',
  1066. 'old' => 'application/x-trash',
  1067. 'sik' => 'application/x-trash',
  1068. 't' => 'application/x-troff',
  1069. 'tr' => 'application/x-troff',
  1070. 'roff' => 'application/x-troff',
  1071. 'man' => 'application/x-troff-man',
  1072. 'me' => 'application/x-troff-me',
  1073. 'ms' => 'application/x-troff-ms',
  1074. 'ustar' => 'application/x-ustar',
  1075. 'src' => 'application/x-wais-source',
  1076. 'wz' => 'application/x-wingz',
  1077. 'crt' => 'application/x-x509-ca-cert',
  1078. 'fig' => 'application/x-xfig',
  1079. 'au' => 'audio/basic',
  1080. 'snd' => 'audio/basic',
  1081. 'mid' => 'audio/midi',
  1082. 'midi' => 'audio/midi',
  1083. 'kar' => 'audio/midi',
  1084. 'mpga' => 'audio/mpeg',
  1085. 'mpega' => 'audio/mpeg',
  1086. 'mp2' => 'audio/mpeg',
  1087. 'mp3' => 'audio/mpeg',
  1088. 'm3u' => 'audio/x-mpegurl',
  1089. 'sid' => 'audio/prs.sid',
  1090. 'aif' => 'audio/x-aiff',
  1091. 'aiff' => 'audio/x-aiff',
  1092. 'aifc' => 'audio/x-aiff',
  1093. 'gsm' => 'audio/x-gsm',
  1094. 'wma' => 'audio/x-ms-wma',
  1095. 'wax' => 'audio/x-ms-wax',
  1096. 'ra' => 'audio/x-realaudio',
  1097. 'rm' => 'audio/x-pn-realaudio',
  1098. 'ram' => 'audio/x-pn-realaudio',
  1099. 'pls' => 'audio/x-scpls',
  1100. 'sd2' => 'audio/x-sd2',
  1101. 'wav' => 'audio/x-wav',
  1102. 'pdb' => 'chemical/x-pdb',
  1103. 'xyz' => 'chemical/x-xyz',
  1104. 'bmp' => 'image/x-ms-bmp',
  1105. 'gif' => 'image/gif',
  1106. 'ief' => 'image/ief',
  1107. 'jpeg' => 'image/jpeg',
  1108. 'jpg' => 'image/jpeg',
  1109. 'jpe' => 'image/jpeg',
  1110. 'pcx' => 'image/pcx',
  1111. 'png' => 'image/png',
  1112. 'svg' => 'image/svg+xml',
  1113. 'svgz' => 'image/svg+xml',
  1114. 'tiff' => 'image/tiff',
  1115. 'tif' => 'image/tiff',
  1116. 'wbmp' => 'image/vnd.wap.wbmp',
  1117. 'ras' => 'image/x-cmu-raster',
  1118. 'cdr' => 'image/x-coreldraw',
  1119. 'pat' => 'image/x-coreldrawpattern',
  1120. 'cdt' => 'image/x-coreldrawtemplate',
  1121. 'djvu' => 'image/x-djvu',
  1122. 'djv' => 'image/x-djvu',
  1123. 'ico' => 'image/x-icon',
  1124. 'art' => 'image/x-jg',
  1125. 'jng' => 'image/x-jng',
  1126. 'psd' => 'image/x-photoshop',
  1127. 'pnm' => 'image/x-portable-anymap',
  1128. 'pbm' => 'image/x-portable-bitmap',
  1129. 'pgm' => 'image/x-portable-graymap',
  1130. 'ppm' => 'image/x-portable-pixmap',
  1131. 'rgb' => 'image/x-rgb',
  1132. 'xbm' => 'image/x-xbitmap',
  1133. 'xpm' => 'image/x-xpixmap',
  1134. 'xwd' => 'image/x-xwindowdump',
  1135. 'igs' => 'model/iges',
  1136. 'iges' => 'model/iges',
  1137. 'msh' => 'model/mesh',
  1138. 'mesh' => 'model/mesh',
  1139. 'silo' => 'model/mesh',
  1140. 'wrl' => 'x-world/x-vrml',
  1141. 'vrml' => 'x-world/x-vrml',
  1142. 'csv' => 'text/comma-separated-values',
  1143. 'css' => 'text/css',
  1144. '323' => 'text/h323',
  1145. 'htm' => 'text/html',
  1146. 'html' => 'text/html',
  1147. 'uls' => 'text/iuls',
  1148. 'mml' => 'text/mathml',
  1149. 'asc' => 'text/plain',
  1150. 'txt' => 'text/plain',
  1151. 'text' => 'text/plain',
  1152. 'diff' => 'text/plain',
  1153. 'rtx' => 'text/richtext',
  1154. 'sct' => 'text/scriptlet',
  1155. 'wsc' => 'text/scriptlet',
  1156. 'tm' => 'text/texmacs',
  1157. 'ts' => 'text/texmacs',
  1158. 'tsv' => 'text/tab-separated-values',
  1159. 'jad' => 'text/vnd.sun.j2me.app-descriptor',
  1160. 'wml' => 'text/vnd.wap.wml',
  1161. 'wmls' => 'text/vnd.wap.wmlscript',
  1162. 'xml' => 'text/xml',
  1163. 'xsl' => 'text/xml',
  1164. 'h++' => 'text/x-c++hdr',
  1165. 'hpp' => 'text/x-c++hdr',
  1166. 'hxx' => 'text/x-c++hdr',
  1167. 'hh' => 'text/x-c++hdr',
  1168. 'c++' => 'text/x-c++src',
  1169. 'cpp' => 'text/x-c++src',
  1170. 'cxx' => 'text/x-c++src',
  1171. 'cc' => 'text/x-c++src',
  1172. 'h' => 'text/x-chdr',
  1173. 'c' => 'text/x-csrc',
  1174. 'java' => 'text/x-java',
  1175. 'moc' => 'text/x-moc',
  1176. 'p' => 'text/x-pascal',
  1177. 'pas' => 'text/x-pascal',
  1178. '***' => 'text/x-pcs-***',
  1179. 'shtml' => 'text/x-server-parsed-html',
  1180. 'etx' => 'text/x-setext',
  1181. 'tk' => 'text/x-tcl',
  1182. 'ltx' => 'text/x-tex',
  1183. 'sty' => 'text/x-tex',
  1184. 'cls' => 'text/x-tex',
  1185. 'vcs' => 'text/x-vcalendar',
  1186. 'vcf' => 'text/x-vcard',
  1187. 'dl' => 'video/dl',
  1188. 'fli' => 'video/fli',
  1189. 'gl' => 'video/gl',
  1190. 'mpeg' => 'video/mpeg',
  1191. 'mpg' => 'video/mpeg',
  1192. 'mpe' => 'video/mpeg',
  1193. 'qt' => 'video/quicktime',
  1194. 'mov' => 'video/quicktime',
  1195. 'mxu' => 'video/vnd.mpegurl',
  1196. 'dif' => 'video/x-dv',
  1197. 'dv' => 'video/x-dv',
  1198. 'lsf' => 'video/x-la-asf',
  1199. 'lsx' => 'video/x-la-asf',
  1200. 'mng' => 'video/x-mng',
  1201. 'asf' => 'video/x-ms-asf',
  1202. 'asx' => 'video/x-ms-asf',
  1203. 'wm' => 'video/x-ms-wm',
  1204. 'wmv' => 'video/x-ms-wmv',
  1205. 'wmx' => 'video/x-ms-wmx',
  1206. 'wvx' => 'video/x-ms-wvx',
  1207. 'avi' => 'video/x-msvideo',
  1208. 'movie' => 'video/x-sgi-movie',
  1209. 'ice' => 'x-conference/x-cooltalk',
  1210. 'vrm' => 'x-world/x-vrml',
  1211. 'rar' => 'application/x-rar-compressed',
  1212. 'cab' => 'application/vnd.ms-cab-compressed'
  1213. );
  1214. $part = explode('.', $fileName);
  1215. $size = count($part);
  1216. if ($size > 1) {
  1217. $ext = $part[$size - 1];
  1218. if (isset($mimeTypes[$ext])) {
  1219. return $mimeTypes[$ext];
  1220. }
  1221. }
  1222. return 'application/octet-stream';
  1223. }
  1224. /**
  1225. * 寻找匹配的mime图标
  1226. *
  1227. * @access public
  1228. * @param string $mime mime类型
  1229. * @return string
  1230. */
  1231. public static function mimeIconType($mime)
  1232. {
  1233. $parts = explode('/', $mime);
  1234. if (count($parts) < 2) {
  1235. return 'unknown';
  1236. }
  1237. list ($type, $stream) = $parts;
  1238. if (in_array($type, array('image', 'video', 'audio', 'text', 'application'))) {
  1239. switch (true) {
  1240. case in_array($stream, array('msword', 'msaccess', 'ms-powerpoint', 'ms-powerpoint')):
  1241. case 0 === strpos($stream, 'vnd.'):
  1242. return 'office';
  1243. case false !== strpos($stream, 'html') || false !== strpos($stream, 'xml') || false !== strpos($stream, 'wml'):
  1244. return 'html';
  1245. case false !== strpos($stream, 'compressed') || false !== strpos($stream, 'zip') ||
  1246. in_array($stream, array('application/x-gtar', 'application/x-tar')):
  1247. return 'archive';
  1248. case 'text' == $type && 0 === strpos($stream, 'x-'):
  1249. return 'script';
  1250. default:
  1251. return $type;
  1252. }
  1253. } else {
  1254. return 'unknown';
  1255. }
  1256. }
  1257. }