PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/php/lib/MTUtil.php

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

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