PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/php/lib/MTUtil.php

http://movable-type-zh-project.googlecode.com/
PHP | 1689 lines | 1503 code | 130 blank | 56 comment | 250 complexity | fbef9e9038ffcfcb3287f09ad2c12299 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. # Movable Type (r) Open Source (C) 2001-2011 Six Apart, Ltd.
  3. # This program is distributed under the terms of the
  4. # GNU General Public License, version 2.
  5. #
  6. # $Id$
  7. function datetime_to_timestamp($dt) {
  8. $dt = preg_replace('/[^0-9]/', '', $dt);
  9. $ts = mktime(substr($dt, 8, 2), substr($dt, 10, 2), substr($dt, 12, 2), substr($dt, 4, 2), substr($dt, 6, 2), substr($dt, 0, 4));
  10. return $ts;
  11. }
  12. function start_end_ts($ts) {
  13. if ($ts) {
  14. if (strlen($ts) == 4) {
  15. $ts_start = $ts . '0101';
  16. $ts_end = $ts . '1231';
  17. } elseif (strlen($ts) == 6) {
  18. $ts_start = $ts . '01';
  19. $ts_end = $ts . sprintf("%02d", days_in(substr($ts, 4, 2), substr($ts, 0, 4)));
  20. } else {
  21. $ts_start = $ts;
  22. $ts_end = $ts;
  23. }
  24. }
  25. return array($ts_start . '000000', $ts_end . '235959');
  26. }
  27. function start_end_month($ts) {
  28. $y = substr($ts, 0, 4);
  29. $mo = substr($ts, 4, 2);
  30. $start = sprintf("%04d%02d01000000", $y, $mo);
  31. $end = sprintf("%04d%02d%02d235959", $y, $mo, days_in($mo, $y));
  32. return array($start, $end);
  33. }
  34. function days_in($m, $y) {
  35. return date('t', mktime(0, 0, 0, $m, 1, $y));
  36. }
  37. function start_end_day($ts) {
  38. $day = substr($ts, 0, 8);
  39. return array($day . "000000", $day . "235959");
  40. }
  41. function start_end_year($ts) {
  42. $year = substr($ts, 0, 4);
  43. return array($year . "0101000000", $year . "1231235959");
  44. }
  45. function start_end_week($ts) {
  46. $y = substr($ts, 0, 4);
  47. $mo = substr($ts, 4, 2);
  48. $d = substr($ts, 6, 2);
  49. $h = substr($ts, 8, 2);
  50. $s = substr($ts, 10, 2);
  51. $wday = wday_from_ts($y, $mo, $d);
  52. list($sd, $sm, $sy) = array($d - $wday, $mo, $y);
  53. if ($sd < 1) {
  54. $sm--;
  55. if ($sm < 1) {
  56. $sm = 12; $sy--;
  57. }
  58. $sd += days_in($sm, $sy);
  59. }
  60. $start = sprintf("%04d%02d%02d%s", $sy, $sm, $sd, "000000");
  61. list($ed, $em, $ey) = array($d + 6 - $wday, $mo, $y);
  62. if ($ed > days_in($em, $ey)) {
  63. $ed -= days_in($em, $ey);
  64. $em++;
  65. if ($em > 12) {
  66. $em = 1; $ey++;
  67. }
  68. }
  69. $end = sprintf("%04d%02d%02d%s", $ey, $em, $ed, "235959");
  70. return array($start, $end);
  71. }
  72. global $In_Year;
  73. $In_Year = array(
  74. array( 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 ),
  75. array( 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 ),
  76. );
  77. function week2ymd($y, $week) {
  78. $jan_one_dow_m1 = (ymd2rd($y, 1, 1) + 6) % 7;
  79. if ($jan_one_dow_m1 < 4) $week--;
  80. $day_of_year = $week * 7 - $jan_one_dow_m1;
  81. $leap_year = is_leap_year($y);
  82. if ($day_of_year < 1) {
  83. $y--;
  84. $day_of_year = ($leap_year ? 366 : 365) + $day_of_year;
  85. }
  86. if ($leap_year) {
  87. $ref = array(0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335);
  88. } else {
  89. $ref = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
  90. }
  91. $m = 0;
  92. for ($i = count($ref); $i > 0; $i--) {
  93. if ($day_of_year > $ref[$i-1]) {
  94. $m = $i;
  95. break;
  96. }
  97. }
  98. return array($y, $m, $day_of_year - $ref[$m-1]);
  99. }
  100. function is_leap_year($y) {
  101. return (!($y % 4) && ($y % 100)) || !($y % 400) ? true : false;
  102. }
  103. function ymd2rd($y,$m,$d) {
  104. # make month in range 3..14 (treat Jan & Feb as months 13..14 of
  105. # prev year)
  106. if ( $m <= 2 ) {
  107. $adj = (int)(( 14 - $m ) / 12);
  108. $y -= $adj;
  109. $m += 12 * $adj;
  110. }
  111. elseif ( $m > 14 )
  112. {
  113. $adj = (int)(( $m - 3 ) / 12);
  114. $y += $adj;
  115. $m -= 12 * $adj;
  116. }
  117. # make year positive (oh, for a use integer 'sane_div'!)
  118. if ( $y < 0 )
  119. {
  120. $adj = (int)(( 399 - $y ) / 400);
  121. $d -= 146097 * $adj;
  122. $y += 400 * $adj;
  123. }
  124. # add: day of month, days of previous 0-11 month period that began
  125. # w/March, days of previous 0-399 year period that began w/March
  126. # of a 400-multiple year), days of any 400-year periods before
  127. # that, and 306 days to adjust from Mar 1, year 0-relative to Jan
  128. # 1, year 1-relative (whew)
  129. $d += (int)(( $m * 367 - 1094 ) / 12) + (int)((($y % 100) * 1461) / 4) +
  130. ( (int)($y / 100) * 36524 + (int)($y / 400) ) - 306;
  131. return $d;
  132. }
  133. function wday_from_ts($y, $m, $d) {
  134. global $In_Year;
  135. $leap = $y % 4 == 0 && ($y % 100 != 0 || $y % 400 == 0) ? 1 : 0;
  136. $y--;
  137. ## Copied from Date::Calc.
  138. $days = $y * 365;
  139. $days += $y >>= 2;
  140. $days -= intval($y /= 25);
  141. $days += $y >> 2;
  142. $days += $In_Year[$leap][$m-1] + $d;
  143. return $days % 7;
  144. }
  145. function yday_from_ts($y, $m, $d) {
  146. global $In_Year;
  147. $leap = $y % 4 == 0 && ($y % 100 != 0 || $y % 400 == 0) ? 1 : 0;
  148. return $In_Year[$leap][$m-1] + $d;
  149. }
  150. function substr_wref($str, $start, $length) {
  151. if (preg_match_all('/(&[^;]*;|.)/', $str, $character_entities)) {
  152. return implode('', array_slice($character_entities[0], $start, $length));
  153. } else {
  154. return '';
  155. }
  156. }
  157. function format_ts($format, $ts, $blog, $lang = null) {
  158. global $Languages;
  159. if (!isset($lang) || empty($lang)) {
  160. $mt = MT::get_instance();
  161. $lang = ($blog && $blog->blog_language ? $blog->blog_language :
  162. $mt->config('DefaultLanguage'));
  163. }
  164. if ($lang == 'jp') {
  165. $lang = 'ja';
  166. }
  167. if ($lang == 'zh_cn') {
  168. $lang = 'zh-cn';
  169. }
  170. if ($lang == 'zh_tw') {
  171. $lang = 'zh-tw';
  172. }
  173. $lang = strtolower(substr($lang, 0, 2));
  174. if (!isset($format) || empty($format)) {
  175. if (count($Languages[$lang]) >= 4)
  176. $format = $Languages[$lang][3];
  177. $format or $format = "%B %e, %Y %l:%M %p";
  178. }
  179. global $_format_ts_cache;
  180. if (!isset($_format_ts_cache)) {
  181. $_format_ts_cache = array();
  182. }
  183. if (isset($_format_ts_cache[$ts.$lang])) {
  184. $f = $_format_ts_cache[$ts.$lang];
  185. } else {
  186. $L = $Languages[$lang];
  187. $tsa = array(substr($ts, 0, 4), substr($ts, 4, 2), substr($ts, 6, 2),
  188. substr($ts, 8, 2), substr($ts, 10, 2), substr($ts, 12, 2));
  189. list($f['Y'], $f['m'], $f['d'], $f['H'], $f['M'], $f['S']) = $tsa;
  190. $f['w'] = wday_from_ts($tsa[0],$tsa[1],$tsa[2]);
  191. $f['j'] = yday_from_ts($tsa[0],$tsa[1],$tsa[2]);
  192. $f['y'] = substr($f['Y'], 2);
  193. $f['b'] = substr_wref($L[1][$f['m']-1], 0, 3);
  194. $f['B'] = $L[1][$f['m']-1];
  195. if ($lang == 'zh-cn') {
  196. $f{a} = '&#21608;' . $L[0][$f['w']];
  197. $f{A} = '&#26143;&#26399;' . $L[0][$f['w']];
  198. } elseif ($lang == 'zh-tw') {
  199. $f{a} = '&#36913;' . $L[0][$f['w']];
  200. $f{A} = '&#31150;&#25308;' . $L[0][$f['w']];
  201. } elseif ($lang == 'ja') {
  202. $f{a} = substr($L[0][$f['w']], 0, 8);
  203. $f{A} = $L[0][$f['w']];
  204. } else {
  205. $f{a} = substr_wref($L[0][$f['w']], 0, 3);
  206. $f{A} = $L[0][$f['w']];
  207. }
  208. $f['e'] = $f['d'];
  209. $f['e'] = preg_replace('!^0!', ' ', $f['e']);
  210. $f['I'] = $f['H'];
  211. if ($f['I'] > 12) {
  212. $f['I'] -= 12;
  213. $f['p'] = $L[2][1];
  214. } elseif ($f['I'] == 0) {
  215. $f['I'] = 12;
  216. $f['p'] = $L[2][0];
  217. } elseif ($f['I'] == 12) {
  218. $f['p'] = $L[2][1];
  219. } else {
  220. $f['p'] = $L[2][0];
  221. }
  222. $f['I'] = sprintf("%02d", $f['I']);
  223. $f['k'] = $f['H'];
  224. $f['k'] = preg_replace('!^0!', ' ', $f['k']);
  225. $f['l'] = $f['I'];
  226. $f['l'] = preg_replace('!^0!', ' ', $f['l']);
  227. $f['j'] = sprintf("%03d", $f['j']);
  228. $f['Z'] = '';
  229. $_format_ts_cache[$ts . $lang] = $f;
  230. }
  231. $date_format = null;
  232. if (count($Languages[$lang]) >= 5)
  233. $date_format = $Languages[$lang][4];
  234. $date_format or $date_format = "%B %e, %Y";
  235. $time_format = null;
  236. if (count($Languages[$lang]) >= 6)
  237. $time_format = $Languages[$lang][5];
  238. $time_format or $time_format = "%l:%M %p";
  239. $format = preg_replace('!%x!', $date_format, $format);
  240. $format = preg_replace('!%X!', $time_format, $format);
  241. ## This is a dreadful hack. I can't think of a good format specifier
  242. ## for "%B %Y" (which is used for monthly archives, for example) so
  243. ## I'll just hardcode this, for Japanese dates.
  244. if ($lang == 'ja' || $lang == 'zh-cn' || $lang == 'zh-tw') {
  245. if (count($Languages[$lang]) >= 8) {
  246. $format = preg_replace('!%B %Y!', $Languages[$lang][6], $format);
  247. $format = preg_replace('!%B %E,? %Y!i', $Languages[$lang][4], $format);
  248. $format = preg_replace('!%B %E!', $Languages[$lang][7], $format);
  249. }
  250. }
  251. elseif ( $lang == 'it' ) {
  252. ## Hack for the Italian dates
  253. ## In Italian, the date always come before the month.
  254. $format = preg_replace('!%b %e!', '%e %b', $format);
  255. }
  256. if (isset($format)) {
  257. $format = preg_replace('!%(\w)!e', '\$f[\'\1\']', $format);
  258. }
  259. return $format;
  260. }
  261. function dirify($s, $sep = '_') {
  262. $mt = MT::get_instance();
  263. $charset = $mt->config('PublishCharset');
  264. $charset or $charset = 'utf-8';
  265. if (preg_match('/utf-?8/i', $charset)) {
  266. return utf8_dirify($s, $sep);
  267. } else {
  268. return iso_dirify($s, $sep);
  269. }
  270. }
  271. function utf8_dirify($s, $sep = '_') {
  272. if ($sep == '1') $sep = '_';
  273. $s = xliterate_utf8($s); ## convert high-ASCII chars to 7bit.
  274. $s = strtolower($s); ## lower-case.
  275. $s = strip_tags($s); ## remove HTML tags.
  276. $s = preg_replace('!&[^;\s]+;!', '', $s); ## remove HTML entities.
  277. $s = preg_replace('![^\w\s]!', '', $s); ## remove non-word/space chars.
  278. $s = preg_replace('/\s+/',$sep,$s); ## change space chars to underscores.
  279. return($s);
  280. }
  281. global $Utf8_ASCII;
  282. $Utf8_ASCII = array(
  283. "\xc3\x80" => 'A', # A`
  284. "\xc3\xa0" => 'a', # a`
  285. "\xc3\x81" => 'A', # A'
  286. "\xc3\xa1" => 'a', # a'
  287. "\xc3\x82" => 'A', # A^
  288. "\xc3\xa2" => 'a', # a^
  289. "\xc4\x82" => 'A', # latin capital letter a with breve
  290. "\xc4\x83" => 'a', # latin small letter a with breve
  291. "\xc3\x86" => 'AE', # latin capital letter AE
  292. "\xc3\xa6" => 'ae', # latin small letter ae
  293. "\xc3\x85" => 'A', # latin capital letter a with ring above
  294. "\xc3\xa5" => 'a', # latin small letter a with ring above
  295. "\xc4\x80" => 'A', # latin capital letter a with macron
  296. "\xc4\x81" => 'a', # latin small letter a with macron
  297. "\xc4\x84" => 'A', # latin capital letter a with ogonek
  298. "\xc4\x85" => 'a', # latin small letter a with ogonek
  299. "\xc3\x84" => 'A', # A:
  300. "\xc3\xa4" => 'a', # a:
  301. "\xc3\x83" => 'A', # A~
  302. "\xc3\xa3" => 'a', # a~
  303. "\xc3\x88" => 'E', # E`
  304. "\xc3\xa8" => 'e', # e`
  305. "\xc3\x89" => 'E', # E'
  306. "\xc3\xa9" => 'e', # e'
  307. "\xc3\x8a" => 'E', # E^
  308. "\xc3\xaa" => 'e', # e^
  309. "\xc3\x8b" => 'E', # E:
  310. "\xc3\xab" => 'e', # e:
  311. "\xc4\x92" => 'E', # latin capital letter e with macron
  312. "\xc4\x93" => 'e', # latin small letter e with macron
  313. "\xc4\x98" => 'E', # latin capital letter e with ogonek
  314. "\xc4\x99" => 'e', # latin small letter e with ogonek
  315. "\xc4\x9a" => 'E', # latin capital letter e with caron
  316. "\xc4\x9b" => 'e', # latin small letter e with caron
  317. "\xc4\x94" => 'E', # latin capital letter e with breve
  318. "\xc4\x95" => 'e', # latin small letter e with breve
  319. "\xc4\x96" => 'E', # latin capital letter e with dot above
  320. "\xc4\x97" => 'e', # latin small letter e with dot above
  321. "\xc3\x8c" => 'I', # I`
  322. "\xc3\xac" => 'i', # i`
  323. "\xc3\x8d" => 'I', # I'
  324. "\xc3\xad" => 'i', # i'
  325. "\xc3\x8e" => 'I', # I^
  326. "\xc3\xae" => 'i', # i^
  327. "\xc3\x8f" => 'I', # I:
  328. "\xc3\xaf" => 'i', # i:
  329. "\xc4\xaa" => 'I', # latin capital letter i with macron
  330. "\xc4\xab" => 'i', # latin small letter i with macron
  331. "\xc4\xa8" => 'I', # latin capital letter i with tilde
  332. "\xc4\xa9" => 'i', # latin small letter i with tilde
  333. "\xc4\xac" => 'I', # latin capital letter i with breve
  334. "\xc4\xad" => 'i', # latin small letter i with breve
  335. "\xc4\xae" => 'I', # latin capital letter i with ogonek
  336. "\xc4\xaf" => 'i', # latin small letter i with ogonek
  337. "\xc4\xb0" => 'I', # latin capital letter with dot above
  338. "\xc4\xb1" => 'i', # latin small letter dotless i
  339. "\xc4\xb2" => 'IJ', # latin capital ligature ij
  340. "\xc4\xb3" => 'ij', # latin small ligature ij
  341. "\xc4\xb4" => 'J', # latin capital letter j with circumflex
  342. "\xc4\xb5" => 'j', # latin small letter j with circumflex
  343. "\xc4\xb6" => 'K', # latin capital letter k with cedilla
  344. "\xc4\xb7" => 'k', # latin small letter k with cedilla
  345. "\xc4\xb8" => 'k', # latin small letter kra
  346. "\xc5\x81" => 'L', # latin capital letter l with stroke
  347. "\xc5\x82" => 'l', # latin small letter l with stroke
  348. "\xc4\xbd" => 'L', # latin capital letter l with caron
  349. "\xc4\xbe" => 'l', # latin small letter l with caron
  350. "\xc4\xb9" => 'L', # latin capital letter l with acute
  351. "\xc4\xba" => 'l', # latin small letter l with acute
  352. "\xc4\xbb" => 'L', # latin capital letter l with cedilla
  353. "\xc4\xbc" => 'l', # latin small letter l with cedilla
  354. "\xc4\xbf" => 'l', # latin capital letter l with middle dot
  355. "\xc5\x80" => 'l', # latin small letter l with middle dot
  356. "\xc3\x92" => 'O', # O`
  357. "\xc3\xb2" => 'o', # o`
  358. "\xc3\x93" => 'O', # O'
  359. "\xc3\xb3" => 'o', # o'
  360. "\xc3\x94" => 'O', # O^
  361. "\xc3\xb4" => 'o', # o^
  362. "\xc3\x96" => 'O', # O:
  363. "\xc3\xb6" => 'o', # o:
  364. "\xc3\x95" => 'O', # O~
  365. "\xc3\xb5" => 'o', # o~
  366. "\xc3\x98" => 'O', # O/
  367. "\xc3\xb8" => 'o', # o/
  368. "\xc5\x8c" => 'O', # latin capital letter o with macron
  369. "\xc5\x8d" => 'o', # latin small letter o with macron
  370. "\xc5\x90" => 'O', # latin capital letter o with double acute
  371. "\xc5\x91" => 'o', # latin small letter o with double acute
  372. "\xc5\x8e" => 'O', # latin capital letter o with breve
  373. "\xc5\x8f" => 'o', # latin small letter o with breve
  374. "\xc5\x92" => 'OE', # latin capital ligature oe
  375. "\xc5\x93" => 'oe', # latin small ligature oe
  376. "\xc5\x94" => 'R', # latin capital letter r with acute
  377. "\xc5\x95" => 'r', # latin small letter r with acute
  378. "\xc5\x98" => 'R', # latin capital letter r with caron
  379. "\xc5\x99" => 'r', # latin small letter r with caron
  380. "\xc5\x96" => 'R', # latin capital letter r with cedilla
  381. "\xc5\x97" => 'r', # latin small letter r with cedilla
  382. "\xc3\x99" => 'U', # U`
  383. "\xc3\xb9" => 'u', # u`
  384. "\xc3\x9a" => 'U', # U'
  385. "\xc3\xba" => 'u', # u'
  386. "\xc3\x9b" => 'U', # U^
  387. "\xc3\xbb" => 'u', # u^
  388. "\xc3\x9c" => 'U', # U:
  389. "\xc3\xbc" => 'u', # u:
  390. "\xc5\xaa" => 'U', # latin capital letter u with macron
  391. "\xc5\xab" => 'u', # latin small letter u with macron
  392. "\xc5\xae" => 'U', # latin capital letter u with ring above
  393. "\xc5\xaf" => 'u', # latin small letter u with ring above
  394. "\xc5\xb0" => 'U', # latin capital letter u with double acute
  395. "\xc5\xb1" => 'u', # latin small letter u with double acute
  396. "\xc5\xac" => 'U', # latin capital letter u with breve
  397. "\xc5\xad" => 'u', # latin small letter u with breve
  398. "\xc5\xa8" => 'U', # latin capital letter u with tilde
  399. "\xc5\xa9" => 'u', # latin small letter u with tilde
  400. "\xc5\xb2" => 'U', # latin capital letter u with ogonek
  401. "\xc5\xb3" => 'u', # latin small letter u with ogonek
  402. "\xc3\x87" => 'C', # ,C
  403. "\xc3\xa7" => 'c', # ,c
  404. "\xc4\x86" => 'C', # latin capital letter c with acute
  405. "\xc4\x87" => 'c', # latin small letter c with acute
  406. "\xc4\x8c" => 'C', # latin capital letter c with caron
  407. "\xc4\x8d" => 'c', # latin small letter c with caron
  408. "\xc4\x88" => 'C', # latin capital letter c with circumflex
  409. "\xc4\x89" => 'c', # latin small letter c with circumflex
  410. "\xc4\x8a" => 'C', # latin capital letter c with dot above
  411. "\xc4\x8b" => 'c', # latin small letter c with dot above
  412. "\xc4\x8e" => 'D', # latin capital letter d with caron
  413. "\xc4\x8f" => 'd', # latin small letter d with caron
  414. "\xc4\x90" => 'D', # latin capital letter d with stroke
  415. "\xc4\x91" => 'd', # latin small letter d with stroke
  416. "\xc3\x91" => 'N', # N~
  417. "\xc3\xb1" => 'n', # n~
  418. "\xc5\x83" => 'N', # latin capital letter n with acute
  419. "\xc5\x84" => 'n', # latin small letter n with acute
  420. "\xc5\x87" => 'N', # latin capital letter n with caron
  421. "\xc5\x88" => 'n', # latin small letter n with caron
  422. "\xc5\x85" => 'N', # latin capital letter n with cedilla
  423. "\xc5\x86" => 'n', # latin small letter n with cedilla
  424. "\xc5\x89" => 'n', # latin small letter n preceded by apostrophe
  425. "\xc5\x8a" => 'N', # latin capital letter eng
  426. "\xc5\x8b" => 'n', # latin small letter eng
  427. "\xc3\x9f" => 'ss', # double-s
  428. "\xc5\x9a" => 'S', # latin capital letter s with acute
  429. "\xc5\x9b" => 's', # latin small letter s with acute
  430. "\xc5\xa0" => 'S', # latin capital letter s with caron
  431. "\xc5\xa1" => 's', # latin small letter s with caron
  432. "\xc5\x9e" => 'S', # latin capital letter s with cedilla
  433. "\xc5\x9f" => 's', # latin small letter s with cedilla
  434. "\xc5\x9c" => 'S', # latin capital letter s with circumflex
  435. "\xc5\x9d" => 's', # latin small letter s with circumflex
  436. "\xc8\x98" => 'S', # latin capital letter s with comma below
  437. "\xc8\x99" => 's', # latin small letter s with comma below
  438. "\xc5\xa4" => 'T', # latin capital letter t with caron
  439. "\xc5\xa5" => 't', # latin small letter t with caron
  440. "\xc5\xa2" => 'T', # latin capital letter t with cedilla
  441. "\xc5\xa3" => 't', # latin small letter t with cedilla
  442. "\xc5\xa6" => 'T', # latin capital letter t with stroke
  443. "\xc5\xa7" => 't', # latin small letter t with stroke
  444. "\xc8\x9a" => 'T', # latin capital letter t with comma below
  445. "\xc8\x9b" => 't', # latin small letter t with comma below
  446. "\xc6\x92" => 'f', # latin small letter f with hook
  447. "\xc4\x9c" => 'G', # latin capital letter g with circumflex
  448. "\xc4\x9d" => 'g', # latin small letter g with circumflex
  449. "\xc4\x9e" => 'G', # latin capital letter g with breve
  450. "\xc4\x9f" => 'g', # latin small letter g with breve
  451. "\xc4\xa0" => 'G', # latin capital letter g with dot above
  452. "\xc4\xa1" => 'g', # latin small letter g with dot above
  453. "\xc4\xa2" => 'G', # latin capital letter g with cedilla
  454. "\xc4\xa3" => 'g', # latin small letter g with cedilla
  455. "\xc4\xa4" => 'H', # latin capital letter h with circumflex
  456. "\xc4\xa5" => 'h', # latin small letter h with circumflex
  457. "\xc4\xa6" => 'H', # latin capital letter h with stroke
  458. "\xc4\xa7" => 'h', # latin small letter h with stroke
  459. "\xc5\xb4" => 'W', # latin capital letter w with circumflex
  460. "\xc5\xb5" => 'w', # latin small letter w with circumflex
  461. "\xc3\x9d" => 'Y', # latin capital letter y with acute
  462. "\xc3\xbd" => 'y', # latin small letter y with acute
  463. "\xc5\xb8" => 'Y', # latin capital letter y with diaeresis
  464. "\xc3\xbf" => 'y', # latin small letter y with diaeresis
  465. "\xc5\xb6" => 'Y', # latin capital letter y with circumflex
  466. "\xc5\xb7" => 'y', # latin small letter y with circumflex
  467. "\xc5\xbd" => 'Z', # latin capital letter z with caron
  468. "\xc5\xbe" => 'z', # latin small letter z with caron
  469. "\xc5\xbb" => 'Z', # latin capital letter z with dot above
  470. "\xc5\xbc" => 'z', # latin small letter z with dot above
  471. "\xc5\xb9" => 'Z', # latin capital letter z with acute
  472. "\xc5\xba" => 'z', # latin small letter z with acute
  473. );
  474. function xliterate_utf8($s) {
  475. global $Utf8_ASCII;
  476. return strtr($s, $Utf8_ASCII);
  477. }
  478. function iso_dirify($s, $sep = '_') {
  479. if ($sep == '1') $sep = '_';
  480. $s = convert_high_ascii($s); ## convert high-ASCII chars to 7bit.
  481. $s = strtolower($s); ## lower-case.
  482. $s = strip_tags($s); ## remove HTML tags.
  483. $s = preg_replace('!&[^;\s]+;!', '', $s); ## remove HTML entities.
  484. $s = preg_replace('![^\w\s]!', '', $s); ## remove non-word/space chars.
  485. $s = preg_replace('/\s+/',$sep,$s); ## change space chars to underscores.
  486. return($s);
  487. }
  488. global $Latin1_ASCII;
  489. $Latin1_ASCII = array(
  490. "\xc0" => 'A', # A`
  491. "\xe0" => 'a', # a`
  492. "\xc1" => 'A', # A'
  493. "\xe1" => 'a', # a'
  494. "\xc2" => 'A', # A^
  495. "\xe2" => 'a', # a^
  496. "\xc4" => 'A', # A:
  497. "\xe4" => 'a', # a:
  498. "\xc5" => 'A', # Aring
  499. "\xe5" => 'a', # aring
  500. "\xc6" => 'AE', # AE
  501. "\xe6" => 'ae', # ae
  502. "\xc3" => 'A', # A~
  503. "\xe3" => 'a', # a~
  504. "\xc8" => 'E', # E`
  505. "\xe8" => 'e', # e`
  506. "\xc9" => 'E', # E'
  507. "\xe9" => 'e', # e'
  508. "\xca" => 'E', # E^
  509. "\xea" => 'e', # e^
  510. "\xcb" => 'E', # E:
  511. "\xeb" => 'e', # e:
  512. "\xcc" => 'I', # I`
  513. "\xec" => 'i', # i`
  514. "\xcd" => 'I', # I'
  515. "\xed" => 'i', # i'
  516. "\xce" => 'I', # I^
  517. "\xee" => 'i', # i^
  518. "\xcf" => 'I', # I:
  519. "\xef" => 'i', # i:
  520. "\xd2" => 'O', # O`
  521. "\xf2" => 'o', # o`
  522. "\xd3" => 'O', # O'
  523. "\xf3" => 'o', # o'
  524. "\xd4" => 'O', # O^
  525. "\xf4" => 'o', # o^
  526. "\xd6" => 'O', # O:
  527. "\xf6" => 'o', # o:
  528. "\xd5" => 'O', # O~
  529. "\xf5" => 'o', # o~
  530. "\xd8" => 'O', # O/
  531. "\xf8" => 'o', # o/
  532. "\xd9" => 'U', # U`
  533. "\xf9" => 'u', # u`
  534. "\xda" => 'U', # U'
  535. "\xfa" => 'u', # u'
  536. "\xdb" => 'U', # U^
  537. "\xfb" => 'u', # u^
  538. "\xdc" => 'U', # U:
  539. "\xfc" => 'u', # u:
  540. "\xc7" => 'C', # ,C
  541. "\xe7" => 'c', # ,c
  542. "\xd1" => 'N', # N~
  543. "\xf1" => 'n', # n~
  544. "\xdd" => 'Y', # Yacute
  545. "\xfd" => 'y', # yacute
  546. "\xdf" => 'ss', # szlig
  547. "\xff" => 'y' # yuml
  548. );
  549. function convert_high_ascii($s) {
  550. $mt = MT::get_instance();
  551. $lang = $mt->config('DefaultLanguage');
  552. if ($lang == 'ja' || $lang == 'zh-cn' || $lang == 'zh-tw') {
  553. $s = mb_convert_encoding($s, 'UTF-8');
  554. return $s;
  555. }
  556. global $Latin1_ASCII;
  557. return strtr($s, $Latin1_ASCII);
  558. }
  559. global $Languages;
  560. $Languages = array(
  561. 'en' => array(
  562. array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'),
  563. array('January','February','March','April','May','June',
  564. 'July','August','September','October','November','December'),
  565. array('AM','PM'),
  566. ),
  567. 'fr' => array(
  568. array('dimanche','lundi','mardi','mercredi','jeudi','vendredi','samedi' ),
  569. array('janvier', "f&#xe9;vrier", 'mars', 'avril', 'mai', 'juin',
  570. 'juillet', "ao&#xfb;t", 'septembre', 'octobre', 'novembre',
  571. "d&#xe9;cembre"),
  572. array('AM','PM'),
  573. ),
  574. 'es' => array(
  575. array('Domingo', 'Lunes', 'Martes', "Mi&#xe9;rcoles", 'Jueves',
  576. 'Viernes', "S&#xe1;bado"),
  577. array('Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto',
  578. 'Septiembre','Octubre','Noviembre','Diciembre'),
  579. array('AM','PM'),
  580. ),
  581. 'pt' => array(
  582. array('domingo', 'segunda-feira', "ter&#xe7;a-feira", 'quarta-feira',
  583. 'quinta-feira', 'sexta-feira', "s&#xe1;bado"),
  584. array('janeiro', 'fevereiro', "mar&#xe7;o", 'abril', 'maio', 'junho',
  585. 'julho', 'agosto', 'setembro', 'outubro', 'novembro',
  586. 'dezembro' ),
  587. array('AM','PM'),
  588. ),
  589. 'nl' => array(
  590. array('zondag','maandag','dinsdag','woensdag','donderdag','vrijdag',
  591. 'zaterdag'),
  592. array('januari','februari','maart','april','mei','juni','juli','augustus',
  593. 'september','oktober','november','december'),
  594. array('am','pm'),
  595. "%d %B %Y %H:%M",
  596. "%d %B %Y"
  597. ),
  598. 'dk' => array(
  599. array("s&#xf8;ndag", 'mandag', 'tirsdag', 'onsdag', 'torsdag',
  600. 'fredag', "l&#xf8;rdag"),
  601. array('januar','februar','marts','april','maj','juni','juli','august',
  602. 'september','oktober','november','december'),
  603. array('am','pm'),
  604. "%d.%m.%Y %H:%M",
  605. "%d.%m.%Y",
  606. "%H:%M",
  607. ),
  608. 'se' => array(
  609. array("s&#xf6;ndag", "m&#xe5;ndag", 'tisdag', 'onsdag', 'torsdag',
  610. 'fredag', "l&#xf6;rdag"),
  611. array('januari','februari','mars','april','maj','juni','juli','augusti',
  612. 'september','oktober','november','december'),
  613. array('FM','EM'),
  614. ),
  615. 'no' => array(
  616. array("S&#xf8;ndag", "Mandag", 'Tirsdag', 'Onsdag', 'Torsdag',
  617. 'Fredag', "L&#xf8;rdag"),
  618. array('Januar','Februar','Mars','April','Mai','Juni','Juli','August',
  619. 'September','Oktober','November','Desember'),
  620. array('FM','EM'),
  621. ),
  622. 'de' => array(
  623. array('Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag',
  624. 'Samstag'),
  625. array('Januar', 'Februar', "M&#xe4;rz", 'April', 'Mai', 'Juni',
  626. 'Juli', 'August', 'September', 'Oktober', 'November',
  627. 'Dezember'),
  628. array('FM','EM'),
  629. "%d.%m.%y %H:%M",
  630. "%d.%m.%y",
  631. "%H:%M",
  632. ),
  633. 'it' => array(
  634. array('Domenica', "Luned&#xec;", "Marted&#xec;", "Mercoled&#xec;",
  635. "Gioved&#xec;", "Venerd&#xec;", 'Sabato'),
  636. array('Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio',
  637. 'Agosto','Settembre','Ottobre','Novembre','Dicembre'),
  638. array('AM','PM'),
  639. "%d.%m.%y %H:%M",
  640. "%d.%m.%y",
  641. "%H:%M",
  642. ),
  643. 'pl' => array(
  644. array('niedziela', "poniedzia&#322;ek", 'wtorek', "&#347;roda",
  645. 'czwartek', "pi&#261;tek", 'sobota'),
  646. array('stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca',
  647. 'lipca', 'sierpnia', "wrze&#347;nia", "pa&#378;dziernika",
  648. 'listopada', 'grudnia'),
  649. array('AM','PM'),
  650. "%e %B %Y %k:%M",
  651. "%e %B %Y",
  652. "%k:%M",
  653. ),
  654. 'fi' => array(
  655. array('sunnuntai','maanantai','tiistai','keskiviikko','torstai','perjantai',
  656. 'lauantai'),
  657. array('tammikuu', 'helmikuu', 'maaliskuu', 'huhtikuu', 'toukokuu',
  658. "kes&#xe4;kuu", "hein&#xe4;kuu", 'elokuu', 'syyskuu', 'lokakuu',
  659. 'marraskuu', 'joulukuu'),
  660. array('AM','PM'),
  661. "%d.%m.%y %H:%M",
  662. ),
  663. 'is' => array(
  664. array('Sunnudagur', "M&#xe1;nudagur", "&#xde;ri&#xf0;judagur",
  665. "Mi&#xf0;vikudagur", 'Fimmtudagur', "F&#xf6;studagur",
  666. 'Laugardagur'),
  667. array("jan&#xfa;ar", "febr&#xfa;ar", 'mars', "apr&#xed;l", "ma&#xed;",
  668. "j&#xfa;n&#xed;", "j&#xfa;l&#xed;", "&#xe1;g&#xfa;st", 'september',
  669. "okt&#xf3;ber", "n&#xf3;vember", 'desember'),
  670. array('FH','EH'),
  671. "%d.%m.%y %H:%M",
  672. ),
  673. 'si' => array(
  674. array('nedelja', 'ponedeljek', 'torek', 'sreda', "&#xe3;etrtek",
  675. 'petek', 'sobota'),
  676. array('januar','februar','marec','april','maj','junij','julij','avgust',
  677. 'september','oktober','november','december'),
  678. array('AM','PM'),
  679. "%d.%m.%y %H:%M",
  680. ),
  681. 'cz' => array(
  682. array('Ned&#283;le', 'Pond&#283;l&#237;', '&#218;ter&#253;',
  683. 'St&#345;eda', '&#268;tvrtek', 'P&#225;tek', 'Sobota'),
  684. array('Leden', '&#218;nor', 'B&#345;ezen', 'Duben', 'Kv&#283;ten',
  685. '&#268;erven', '&#268;ervenec', 'Srpen', 'Z&#225;&#345;&#237;',
  686. '&#216;&#237;jen', 'Listopad', 'Prosinec'),
  687. array('AM','PM'),
  688. "%e. %B %Y %k:%M",
  689. "%e. %B %Y",
  690. "%k:%M",
  691. ),
  692. 'sk' => array(
  693. array('nede&#318;a', 'pondelok', 'utorok', 'streda',
  694. '&#353;tvrtok', 'piatok', 'sobota'),
  695. array('janu&#225;r', 'febru&#225;r', 'marec', 'apr&#237;l',
  696. 'm&#225;j', 'j&#250;n', 'j&#250;l', 'august', 'september',
  697. 'okt&#243;ber', 'november', 'december'),
  698. array('AM','PM'),
  699. "%e. %B %Y %k:%M",
  700. "%e. %B %Y",
  701. "%k:%M",
  702. ),
  703. 'jp' => array(
  704. array('&#26085;&#26332;&#26085;', '&#26376;&#26332;&#26085;',
  705. '&#28779;&#26332;&#26085;', '&#27700;&#26332;&#26085;',
  706. '&#26408;&#26332;&#26085;', '&#37329;&#26332;&#26085;',
  707. '&#22303;&#26332;&#26085;'),
  708. array('1','2','3','4','5','6','7','8','9','10','11','12'),
  709. array('AM','PM'),
  710. "%Y&#24180;%b&#26376;%e&#26085; %H:%M",
  711. "%Y&#24180;%b&#26376;%e&#26085;",
  712. "%H:%M",
  713. "%Y&#24180;%b&#26376;",
  714. "%b&#26376;%e&#26085;",
  715. ),
  716. 'ja' => array(
  717. array('&#26085;&#26332;&#26085;', '&#26376;&#26332;&#26085;',
  718. '&#28779;&#26332;&#26085;', '&#27700;&#26332;&#26085;',
  719. '&#26408;&#26332;&#26085;', '&#37329;&#26332;&#26085;',
  720. '&#22303;&#26332;&#26085;'),
  721. array('1','2','3','4','5','6','7','8','9','10','11','12'),
  722. array('AM','PM'),
  723. "%Y&#24180;%b&#26376;%e&#26085; %H:%M",
  724. "%Y&#24180;%b&#26376;%e&#26085;",
  725. "%H:%M",
  726. "%Y&#24180;%b&#26376;",
  727. "%b&#26376;%e&#26085;",
  728. ),
  729. 'zh-cn' => array(
  730. array( '&#26085;', '&#19968;',
  731. '&#20108;', '&#19977;',
  732. '&#22235;', '&#20116;',
  733. '&#20845;'),
  734. array('1','2','3','4','5','6','7','8','9','10','11','12'),
  735. array('AM','PM'),
  736. "%Y&#24180;%b&#26376;%e&#26085; %H:%M",
  737. "%Y&#24180;%b&#26376;%e&#26085;",
  738. "%H:%M",
  739. "%Y&#24180;%b&#26376;",
  740. "%b&#26376;%e&#26085;",
  741. ),
  742. 'zh_cn' => array(
  743. array( '&#26085;', '&#19968;',
  744. '&#20108;', '&#19977;',
  745. '&#22235;', '&#20116;',
  746. '&#20845;'),
  747. array('1','2','3','4','5','6','7','8','9','10','11','12'),
  748. array('AM','PM'),
  749. "%Y&#24180;%b&#26376;%e&#26085; %H:%M",
  750. "%Y&#24180;%b&#26376;%e&#26085;",
  751. "%H:%M",
  752. "%Y&#24180;%b&#26376;",
  753. "%b&#26376;%e&#26085;",
  754. ),
  755. 'zh-tw' => array(
  756. array( '&#26085;', '&#19968;',
  757. '&#20108;', '&#19977;',
  758. '&#22235;', '&#20116;',
  759. '&#20845;'),
  760. array('1','2','3','4','5','6','7','8','9','10','11','12'),
  761. array('AM','PM'),
  762. "%Y&#24180;%b&#26376;%e&#26085; %H:%M",
  763. "%Y&#24180;%b&#26376;%e&#26085;",
  764. "%H:%M",
  765. "%Y&#24180;%b&#26376;",
  766. "%b&#26376;%e&#26085;",
  767. ),
  768. 'zh_tw' => array(
  769. array( '&#26085;', '&#19968;',
  770. '&#20108;', '&#19977;',
  771. '&#22235;', '&#20116;',
  772. '&#20845;'),
  773. array('1','2','3','4','5','6','7','8','9','10','11','12'),
  774. array('AM','PM'),
  775. "%Y&#24180;%b&#26376;%e&#26085; %H:%M",
  776. "%Y&#24180;%b&#26376;%e&#26085;",
  777. "%H:%M",
  778. "%Y&#24180;%b&#26376;",
  779. "%b&#26376;%e&#26085;",
  780. ),
  781. 'et' => array(
  782. array('ip&uuml;hap&auml;ev','esmasp&auml;ev','teisip&auml;ev',
  783. 'kolmap&auml;ev','neljap&auml;ev','reede','laup&auml;ev'),
  784. array('jaanuar', 'veebruar', 'm&auml;rts', 'aprill', 'mai',
  785. 'juuni', 'juuli', 'august', 'september', 'oktoober',
  786. 'november', 'detsember'),
  787. array('AM','PM'),
  788. "%m.%d.%y %H:%M",
  789. "%e. %B %Y",
  790. "%H:%M",
  791. ),
  792. );
  793. global $_encode_xml_Map;
  794. $_encode_xml_Map = array('&' => '&amp;', '"' => '&quot;',
  795. '<' => '&lt;', '>' => '&gt;',
  796. '\'' => '&apos;');
  797. function encode_xml($str, $nocdata = 0) {
  798. $mt = MT::get_instance();
  799. global $_encode_xml_Map;
  800. $cfg_nocdata = $mt->config('NoCDATA');
  801. $nocdata or (isset($cfg_nocdata) and $nocdata = $cfg_nocdata);
  802. if ((!$nocdata) && (preg_match('/
  803. <[^>]+> ## HTML markup
  804. | ## or
  805. &(?:(?!(\#([0-9]+)|\#x([0-9a-fA-F]+))).*?);
  806. ## something that looks like an HTML entity.
  807. /x', $str))) {
  808. ## If ]]> exists in the string, encode the > to &gt;.
  809. $str = preg_replace('/]]>/', ']]&gt;', $str);
  810. $str = '<![CDATA[' . $str . ']]>';
  811. } else {
  812. $str = strtr($str, $_encode_xml_Map);
  813. $str = preg_replace('/&amp;((\#([0-9]+)|\#x([0-9a-fA-F]+)).*?);/', "&$1;", $str);
  814. }
  815. return $str;
  816. }
  817. function decode_xml($str) {
  818. if (preg_match('/<!\[CDATA\[(.*?)]]>/', $str)) {
  819. $str = preg_replace('/<!\[CDATA\[(.*?)]]>/', '\1', $str);
  820. ## Decode encoded ]]&gt;
  821. $str = preg_replace('/]]&(gt|#62);/', ']]>', $str);
  822. } else {
  823. global $_encode_xml_Map;
  824. $str = strtr($str, array_flip($_encode_xml_Map));
  825. }
  826. return $str;
  827. }
  828. function encode_js($str) {
  829. if (!isset($str)) return '';
  830. $str = preg_replace('!\\\\!', '\\\\', $str);
  831. $str = preg_replace('!>!', '\\>', $str);
  832. $str = preg_replace('!<!', '\\<', $str);
  833. $str = preg_replace('!(s)(cript)!i', '$1\\\\$2', $str);
  834. $str = preg_replace('!</!', '<\\/', $str); # </ is supposed to be the end of Javascript (</script in most UA)
  835. $str = preg_replace('!\'!', '\\\'', $str);
  836. $str = preg_replace('!"!', '\\"', $str);
  837. $str = preg_replace('!\n!', '\\n', $str);
  838. $str = preg_replace('!\f!', '\\f', $str);
  839. $str = preg_replace('!\r!', '\\r', $str);
  840. $str = preg_replace('!\t!', '\\t', $str);
  841. return $str;
  842. }
  843. function gmtime($ts = null) {
  844. if (!isset($ts)) {
  845. $ts = time();
  846. }
  847. $offset = date('Z', $ts);
  848. $ts -= $offset;
  849. $tsa = localtime($ts);
  850. $tsa[8] = 0;
  851. return $tsa;
  852. }
  853. function is_hash($array) {
  854. if ( is_array($array) ) {
  855. if ( array_keys($array) === range(0, count($array) - 1) ) {
  856. // 0,1,2,3... must be an array
  857. return false;
  858. }
  859. return true;
  860. }
  861. return false;
  862. }
  863. function offset_time_list($ts, $blog = null, $dir = null) {
  864. return gmtime(offset_time($ts, $blog, $dir));
  865. }
  866. function strip_hyphen($s) {
  867. return preg_replace('/-+/', '-', $s);
  868. }
  869. function first_n_words($text, $n) {
  870. $text = strip_tags($text);
  871. $words = preg_split('/\s+/', $text);
  872. $max = count($words) > $n ? $n : count($words);
  873. return join(' ', array_slice($words, 0, $max));
  874. }
  875. function html_text_transform($str = '') {
  876. $paras = preg_split('/\r?\n\r?\n/', $str);
  877. if ($str == '') {
  878. return '';
  879. }
  880. foreach ($paras as $k => $p) {
  881. if (!preg_match('/^<\/?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|select|fieldset|blockquote|address|div|hr)/', $p)) {
  882. $p = preg_replace('/\r?\n/', "<br />\n", $p);
  883. $p = "<p>$p</p>";
  884. $paras[$k] = $p;
  885. }
  886. }
  887. return implode("\n\n", $paras);
  888. }
  889. function encode_html($str, $quote_style = ENT_COMPAT) {
  890. if (!isset($str)) return '';
  891. $trans_table = get_html_translation_table(HTML_SPECIALCHARS, $quote_style);
  892. if( $trans_table["'"] != '&#039;' ) { # some versions of PHP match single quotes to &#39;
  893. $trans_table["'"] = '&#039;';
  894. }
  895. return (strtr($str, $trans_table));
  896. }
  897. function decode_html($str, $quote_style = ENT_COMPAT) {
  898. if (!isset($str)) return '';
  899. $trans_table = get_html_translation_table(HTML_SPECIALCHARS, $quote_style);
  900. if( $trans_table["'"] != '&#039;' ) { # some versions of PHP match single quotes to &#39;
  901. $trans_table["'"] = '&#039;';
  902. }
  903. return (strtr($str, array_flip($trans_table)));
  904. }
  905. function get_category_context(&$ctx, $class = 'category') {
  906. # Get our hands on the category for the current context
  907. # Either in MTCategories, a Category Archive Template
  908. # Or the category for the current entry
  909. $cat = $ctx->stash('category') or
  910. $ctx->stash('archive_category');
  911. if (!isset($cat)) {
  912. # No category found so far, test the entry
  913. if ($ctx->stash('entry')) {
  914. $entry = $ctx->stash('entry');
  915. $place = $entry->placement();
  916. if (empty($place))
  917. return null;
  918. $cat = $place[0]->category();
  919. # Return empty string if entry has no category
  920. # as the tag has been used in the correct context
  921. # but there is no category to work with
  922. if (!isset($cat)) {
  923. return null;
  924. }
  925. } else {
  926. $tag = $ctx->this_tag();
  927. return $ctx->error("$tag must be used in a category context");
  928. }
  929. }
  930. return $cat;
  931. }
  932. function munge_comment($text, $blog) {
  933. if (!$blog->blog_allow_comment_html) {
  934. $text = strip_tags($text);
  935. }
  936. if ($blog->blog_autolink_urls) {
  937. $text = preg_replace('!(^|\s|>)(https?://[^\s<]+)!s', '$1<a href="$2">$2</a>', $text);
  938. }
  939. return $text;
  940. }
  941. function length_text($text) {
  942. if (!extension_loaded('mbstring')) {
  943. $len = strlen($text);
  944. } else {
  945. $len = mb_strlen($text);
  946. }
  947. return $len;
  948. }
  949. function substr_text($text, $startpos, $length) {
  950. if (!extension_loaded('mbstring')) {
  951. $text = substr($text, $startpos, $length);
  952. } else {
  953. $text = mb_substr($text, $startpos, $length);
  954. }
  955. return $text;
  956. }
  957. function first_n_text($text, $n) {
  958. if (!isset($lang) || empty($lang)) {
  959. $mt = MT::get_instance();
  960. $lang = ($blog && $blog->blog_language ? $blog->blog_language :
  961. $mt->config('DefaultLanguage'));
  962. }
  963. if ($lang == 'jp') {
  964. $lang = 'ja';
  965. }
  966. if ($lang == 'ja') {
  967. $text = strip_tags($text);
  968. $text = preg_replace('/\r?\n/', " ", $text);
  969. return substr_text($text, 0, $n);
  970. }else{
  971. return first_n_words($text, $n);
  972. }
  973. }
  974. function tag_split_delim($delim, $str) {
  975. $delim = quotemeta($delim);
  976. $tags = array();
  977. $str = trim($str);
  978. while (strlen($str) && (preg_match("/^(((['\"])(.*?)\3[^$delim]*?|.*?)($delim\s*|$))/s", $str, $match))) {
  979. $str = substr($str, strlen($match[1]));
  980. $tag = (isset($match[4]) && $match[4] != '') ? $match[4] : $match[2];
  981. $tag = trim($tag);
  982. $tag = preg_replace('/\s+/', ' ', $tag);
  983. $n8d_tag = tag_normalize($tag);
  984. if ($n8d_tag != '')
  985. if ($tag != '') $tags[] = $tag;
  986. }
  987. return $tags;
  988. }
  989. function tag_split($str) {
  990. return tag_split_delim(',', $str);
  991. }
  992. function catarray_path_length_sort($a, $b) {
  993. $al = strlen($a->category_label_path);
  994. $bl = strlen($bcategory_label_path);
  995. return $al == $bl ? 0 : $al < $bl ? 1 : -1;
  996. }
  997. # sorts by length of category label, from longest to shortest
  998. function catarray_length_sort($a, $b) {
  999. $al = strlen($a->category_label);
  1000. $bl = strlen($b->category_label);
  1001. return $al == $bl ? 0 : $al < $bl ? 1 : -1;
  1002. }
  1003. function create_expr_exception($m) {
  1004. if ($m[2])
  1005. return '(0)';
  1006. else
  1007. return $m[1];
  1008. }
  1009. function create_cat_expr_function($expr, &$cats, $param) {
  1010. $mt = MT::get_instance();
  1011. $cats_used = array();
  1012. $orig_expr = $expr;
  1013. $include_children = $param['children'] ? 1 : 0;
  1014. $cats_used = array();
  1015. if (preg_match('/\//', $expr)) {
  1016. foreach ($cats as $id => $cat) {
  1017. $catp = category_label_path($cat);
  1018. $cats[$id]->category_label_path = $catp;
  1019. }
  1020. $cols = array('category_label_path', 'category_label');
  1021. } else {
  1022. $cols = array('category_label');
  1023. }
  1024. foreach ($cols as $col) {
  1025. if ($col == 'category_label_path') {
  1026. usort($cats, 'catarray_path_length_sort');
  1027. } else {
  1028. usort($cats, 'catarray_length_sort');
  1029. }
  1030. $cats_replaced = array();
  1031. foreach ($cats as $cat) {
  1032. $catl = $cat->$col;
  1033. $catid = $cat->category_id;
  1034. $catre = preg_quote($catl, "/");
  1035. if (!preg_match("/(?:(?<![#\d])\[$catre\]|$catre)|(?:#$catid\b)/", $expr))
  1036. continue;
  1037. if ($include_children) {
  1038. $kids = array($cat);
  1039. $child_cats = array();
  1040. while ($c = array_shift($kids)) {
  1041. $child_cats[$c->category_id] = $c;
  1042. $children = $mt->db()->fetch_categories(array('category_id' => $c->category_id, 'children' => 1, 'show_empty' => 1, 'class' => $c->category_class));
  1043. if ($children) {
  1044. foreach ($children as $child) {
  1045. $kids[] = $child;
  1046. }
  1047. }
  1048. }
  1049. $repl = '';
  1050. foreach ($child_cats as $ccid => $cc) {
  1051. $repl .= '||#' . $ccid;
  1052. }
  1053. if (strlen($repl)) $repl = substr($repl, 2);
  1054. $repl = '(' . $repl . ')';
  1055. } else {
  1056. $repl = "(#$catid)";
  1057. }
  1058. if (isset($cats_replaced[$catl])) {
  1059. $last_catid = $cats_replaced[$catl];
  1060. $expr = preg_replace("/(#$last_catid\b)/", '($1 || #' . $catid . ')', $expr);
  1061. } else {
  1062. $expr = preg_replace("/(?:(?<!#)(?:\[$catre\]|$catre))|#$catid\b/", $repl,
  1063. $expr);
  1064. $cats_replaced[$catl] = $catid;
  1065. }
  1066. if ($include_children) {
  1067. foreach ($child_cats as $ccid => $cc)
  1068. $cats_used[$ccid] = $cc;
  1069. } else {
  1070. $cats_used[$catid] = $cat;
  1071. }
  1072. }
  1073. }
  1074. $expr = preg_replace('/\bAND\b/i', '&&', $expr);
  1075. $expr = preg_replace('/\bOR\b/i', '||', $expr);
  1076. $expr = preg_replace('/\bNOT\b/i', '!', $expr);
  1077. $expr = preg_replace_callback('/( |#\d+|&&|\|\||!|\(|\))|([^#0-9&|!()]+)/', 'create_expr_exception', $expr);
  1078. # strip out all the 'ok' stuff. if anything is left, we have
  1079. # some invalid data in our expression:
  1080. $test_expr = preg_replace('/!|&&|\|\||\(0\)|\(|\)|\s|#\d+/', '', $expr);
  1081. if ($test_expr != '') {
  1082. echo "Invalid category filter: $orig_expr";
  1083. return;
  1084. }
  1085. if (!preg_match('/!/', $expr))
  1086. $cats = array_values($cats_used);
  1087. $expr = preg_replace('/#(\d+)/', "array_key_exists('\\1', \$pm)", $expr);
  1088. $expr = '$pm = array_key_exists($e->entry_id, $c["p"]) ? $c["p"][$e->entry_id] : array(); return (' . $expr . ');';
  1089. $fn = create_function('&$e,&$c', $expr);
  1090. if ($fn === FALSE) {
  1091. echo "Invalid category filter: $orig_expr";
  1092. return;
  1093. }
  1094. return $fn;
  1095. }
  1096. function category_label_path($cat) {
  1097. $mt = MT::get_instance();
  1098. $mtdb =& $mt->db();
  1099. if (isset($cat->__label_path))
  1100. return $cat->__label_path;
  1101. $result = preg_match('/\//', $cat->category_label) ? '[' . $cat->category_label . ']' : $cat->category_label;
  1102. while ($cat) {
  1103. $cat = $cat->category_parent ? $mtdb->fetch_category($cat->category_parent) : null;
  1104. if ($cat)
  1105. $result = (preg_match('/\//', $cat->category_label) ? '[' . $cat->category_label . ']' : $cat->category_label) . '/' . $result;
  1106. }
  1107. # caching this information may be problematic IF
  1108. # parent category labels are changed.
  1109. $cat->__label_path = $result;
  1110. return $result;
  1111. }
  1112. function cat_path_to_category($path, $blogs = null, $class = 'category') {
  1113. $mt = MT::get_instance();
  1114. if (!$blogs) {
  1115. $ctx = $mt->context();
  1116. $blogs = array('include_blogs' => $ctx->stash('blog_id'));
  1117. }
  1118. if (!is_array($blogs))
  1119. $blogs = array($blogs);
  1120. $mtdb =& $mt->db();
  1121. if (preg_match_all('/(\[[^]]+?\]|[^]\/]+)/', $path, $matches)) {
  1122. # split on slashes, fields quoted by []
  1123. $cat_path = $matches[1];
  1124. for ($i = 0; $i < count($cat_path); $i++) {
  1125. $cat_path[$i] = preg_replace('/^\[(.*)\]$/', '\1', $cat_path[$i]); # remove any []
  1126. }
  1127. $last_cat_ids = array(0);
  1128. foreach ($cat_path as $label) {
  1129. $cats = $mtdb->fetch_categories(array_merge($blogs, array('label' => $label, 'parent' => $last_cat_ids, 'show_empty' => 1, 'class' => $class)));
  1130. if (!$cats)
  1131. break;
  1132. $last_cat_ids = array();
  1133. foreach ($cats as $cat)
  1134. $last_cat_ids[] = $cat->category_id;
  1135. }
  1136. }
  1137. if ($cats)
  1138. return $cats;
  1139. if (!$cats && $path) {
  1140. $cats = $mtdb->fetch_categories(array_merge($blogs, array('label' => $path, 'show_empty' => 1, 'class' => $class)));
  1141. if ($cats)
  1142. return $cats;
  1143. }
  1144. return null;
  1145. }
  1146. # sorts by length of tag name, from longest to shortest
  1147. function tagarray_name_sort($a, $b) {
  1148. return strcmp(strtolower($a->tag_name), strtolower($b->tag_name));
  1149. }
  1150. function tagarray_length_sort($a, $b) {
  1151. $al = strlen($a->tag_name);
  1152. $bl = strlen($b->tag_name);
  1153. return $al == $bl ? 0 : $al < $bl ? 1 : -1;
  1154. }
  1155. function create_tag_expr_function($expr, &$tags, $datasource = 'entry') {
  1156. $tags_used = array();
  1157. $orig_expr = $expr;
  1158. # Sort in descending order by length
  1159. usort($tags, 'tagarray_length_sort');
  1160. # Modify the tag argument, replacing the tag name with '#TagID'
  1161. # Create a ID-based hash of the tags that are used in the arg
  1162. foreach ($tags as $tag) {
  1163. $tagn = str_replace('/', '\/', $tag->tag_name);
  1164. $tagid = $tag->tag_id;
  1165. $oldexpr = $expr;
  1166. $expr = preg_replace("/(\sAND\s|\sOR\s|\s?NOT\s|\(|\A)\s*?\Q$tagn\E\s*?(\Z|\)|\sAND\s|\sOR\s|\sNOT\s)/", "#$tagid",
  1167. $expr);
  1168. if ($oldexpr != $expr)
  1169. $tags_used[$tagid] = $tag;
  1170. }
  1171. # Replace logical constructs with their PHP equivalents
  1172. $expr = preg_replace('/\bAND\b/i', '&&', $expr);
  1173. $expr = preg_replace('/\bOR\b/i', '||', $expr);
  1174. $expr = preg_replace('/\bNOT\b/i', '!', $expr);
  1175. # The following is no more readable in PHP than it is in Perl
  1176. $expr = preg_replace_callback('/( |\#\d+|&&|\|\||!|\(|\))|([^#&|!()]+)/', 'create_expr_exception', $expr);
  1177. # Syntax check on 'tag' argument
  1178. # Strip out all the valid stuff. if anything is left, we have
  1179. # some invalid data in our expression
  1180. $test_expr = preg_replace('/!|&&|\|\||\(0\)|\(|\)|\s|#\d+/', '', $expr);
  1181. if ($test_expr != '') {
  1182. echo "Invalid tag filter: $orig_expr";
  1183. return;
  1184. }
  1185. # Populate array (passed in by reference) of used tags
  1186. $tags = array_values($tags_used);
  1187. # Replace '#TagID' with a hash lookup function.
  1188. # Function confirms/denies use of tag on entry (by IDs)
  1189. $column_name = $datasource . '_id';
  1190. $expr = preg_replace('/#(\d+)/', "array_key_exists('\\1', \$tm)", $expr);
  1191. # Create a PHP-blessed function of that code and return it
  1192. # if all is well. This function will be used later to
  1193. # test for existence of specified tags in entries.
  1194. $expr = '$tm = array_key_exists($e->'.$datasource.'_id, $c["t"]) ? $c["t"][$e->'.$datasource.'_id] : array(); return ' . $expr .
  1195. ';';
  1196. $fn = create_function('&$e,&$c', $expr);
  1197. if ($fn === FALSE) {
  1198. echo "Invalid tag filter: $orig_expr";
  1199. return;
  1200. }
  1201. return $fn;
  1202. }
  1203. function tag_normalize($str) {
  1204. # FIXME: character set issues here...
  1205. $private = preg_match('/^@/', $str) ? 1 : 0;
  1206. $str = preg_replace('/[@!`\\<>\*&#\/~\?\'"\.\,=\(\)\${}\[\];:\ \+\-\r\n]+/', '', $str);
  1207. $str = strtolower($str);
  1208. if ($private) $str = '@' . $str;
  1209. return $str;
  1210. }
  1211. function static_path($host) {
  1212. $mt = MT::get_instance();
  1213. $path = $mt->config('StaticWebPath');
  1214. if (!$path) {
  1215. $path = $mt->config('CGIPath');
  1216. if (substr($path, 0, 1) == '/') { # relative
  1217. if (!preg_match('!/$!', $host))
  1218. $host .= '/';
  1219. if (preg_match('!^(https?://[^/:]+)(:\d+)?/!', $host, $matches)) {
  1220. $path = $matches[1] . $path;
  1221. }
  1222. }
  1223. if (substr($path, strlen($path) - 1, 1) != '/')
  1224. $path .= '/';
  1225. $path .= 'mt-static/';
  1226. } elseif (substr($path, 0, 1) == '/') {
  1227. if (!preg_match('!/$!', $host))
  1228. $host .= '/';
  1229. if (preg_match('!^(https?://[^/:]+)(:\d+)?/!', $host, $matches)) {
  1230. $path = $matches[1] . $path;
  1231. }
  1232. }
  1233. if (substr($path, strlen($path) - 1, 1) != '/')
  1234. $path .= '/';
  1235. return $path;
  1236. }
  1237. function static_file_path() {
  1238. $mt = MT::get_instance();
  1239. $path = $mt->config('StaticFilePath');
  1240. if (!$path) {
  1241. $path = dirname(dirname(dirname(__FILE__)));
  1242. $path .= DIRECTORY_SEPARATOR . 'mt-static' . DIRECTORY_SEPARATOR;
  1243. }
  1244. if (substr($path, strlen($path) - 1, 1) != DIRECTORY_SEPARATOR)
  1245. $path .= DIRECTORY_SEPARATOR;
  1246. return $path;
  1247. }
  1248. function support_directory_url() {
  1249. $mt = MT::get_instance();
  1250. $url = $mt->config('SupportDirectoryURL');
  1251. if (!$url) {
  1252. $url = static_path('');
  1253. $url .= 'support/';
  1254. }
  1255. elseif (!preg_match('!/$!', $url) ) {

Large files files are truncated, but you can click here to view the full file