PageRenderTime 67ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/php/lib/MTUtil.php

https://code.google.com/p/movabletype/
PHP | 1689 lines | 1506 code | 127 blank | 56 comment | 232 complexity | a7b9f66679f1db91a2042b0e633ff907 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.1

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

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