PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/dewberry/dewberry/inc/tags.php

http://goodgirl.googlecode.com/
PHP | 641 lines | 499 code | 113 blank | 29 comment | 77 complexity | f37afa91418c042a925d6ce7c3eb1a90 MD5 | raw file
  1. <?php /* `,
  2. ,\, #
  3. D E W B E R R Y |/ ?
  4. <http://goodgirl.ru/dewberry> | ~ )\
  5. <http://goodgirl.ru/dewberry/license> /__/\ \____
  6. / \_/ \
  7. ???? zloy ? ???????? <http://lexa.cutenews.ru> / <_ ____,_-/\ __
  8. ---------------------------------------------------------/___/_____ \--'\|/----
  9. \/|*/
  10. // HTML++ ??? HTML#, ???? ?? ?????????? ?????? ?? MS Windows.
  11. // ?????? ??? ??? ????? ????.
  12. class Tags extends Attr {
  13. static $ns;
  14. static $var = '$GLOBALS';
  15. ////////////////////////////////////////////////////////////////////////////////
  16. function parse($output, $is_final = false){
  17. $output = self::parse_vars($output);
  18. $output = self::parse_supadupa($output, $is_final);
  19. $output = self::sux('<berry>'.$output.'</berry>');
  20. $values = array();
  21. $parser = xml_parser_create();
  22. xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
  23. xml_parse_into_struct($parser, $output, $values) or self::_errors($parser, $output);
  24. xml_parser_free($parser);
  25. $result = self::_values($values, $is_final);
  26. $result = str_replace(array('<berry>', '</berry>', '<berry />'), '', $result);
  27. $result = ($is_final ? self::unsux($result) : $result);
  28. return $result;
  29. }
  30. ////////////////////////////////////////////////////////////////////////////////
  31. function parse_else($if, $output){ $arr = preg_split('/<else( ([^>]*))?\/>/i', $output, 2);
  32. return ($if ? $arr[0] : $arr[1]); }
  33. ////////////////////////////////////////////////////////////////////////////////
  34. protected function _errors($parser, $output){ $output = str_replace(array('<berry>', '</berry>', '<berry />'), '', $output);
  35. $code = xml_get_error_code($parser);
  36. $lines = $href = array();
  37. libxml_use_internal_errors(true);
  38. simplexml_load_string($output);
  39. foreach (libxml_get_errors() as $error)
  40. if ($error->code == $code){ if (preg_match('/line (\d+)/', $error->message, $match))
  41. $lines[] = $match[1];
  42. else
  43. $lines[] = $error->line;
  44. }
  45. sort($lines);
  46. foreach ($lines as $line)
  47. $href[] = '<a href="#'.$line.'">'.$line.'</a>';
  48. echo '<h1>'.xml_error_string($code).'</h1>';
  49. echo '<h2>Line(s): '.join(', ', $href).'</h2>';
  50. echo '<table>';
  51. foreach (explode("\n", self::unsux($output)) as $k => $v){ $i = ($k + 1);
  52. $bg = (in_array($i, $lines) ? 'ffe6e6' : 'f3f3f3');
  53. echo '<tr>';
  54. echo '<td style="background: #ccc; padding: 5px;">';
  55. echo '<a name="'.($i + 1).'"></a>'.$i;
  56. echo '<td style="background: #'.$bg.'; padding: 5px;">';
  57. echo '<pre>'.self::unhtml($v).'</pre>';
  58. }
  59. exit;
  60. }
  61. ////////////////////////////////////////////////////////////////////////////////
  62. function skip($tag = ''){
  63. static $skip = array();
  64. if ($tag)
  65. $skip[] = strtolower($tag);
  66. return $skip;
  67. }
  68. ////////////////////////////////////////////////////////////////////////////////
  69. function parse_vars($output){
  70. $output = str_replace('\#', self::char('#'), $output);
  71. $output = str_replace('\$', self::char('$'), $output);
  72. if (preg_match_all('/(#|\$|\$\w+){([^}]*)}/U', $output, $match))
  73. for ($i = 0, $c = count($match[0]); $i < $c; $i++)
  74. if ($pos = strpos($match[2][$i], '=')){
  75. $k = trim(substr($match[2][$i], 0, $pos));
  76. $v = trim(substr($match[2][$i], $pos + 1));
  77. if (($v[0] == "'" and substr($v, -1) == "'") or ($v[0] == '"' and substr($v, -1) == '"')){
  78. $v = substr($v, 1, -1);
  79. } elseif ($f = create_function('', 'return '.$v.';')){
  80. $v = $f();
  81. }
  82. if ($match[1][$i] == '#')
  83. self::constant($k, $v);
  84. elseif ($match[1][$i][0] == '$')
  85. self::vars($k, $v);
  86. $output = str_replace($match[0][$i], '', $output);
  87. } else {
  88. if ($match[1][$i] == '#'){
  89. $output = str_replace($match[0][$i], self::constant($match[2][$i]), $output);
  90. continue;
  91. }
  92. $var = self::vars($match[2][$i]);
  93. $match[1][$i] = strtolower($match[1][$i]);
  94. if (($type = substr($match[1][$i], 1)) and function_exists($func = 'type_'.$type))
  95. $result = call_user_func($func, $match[2][$i], $var);
  96. else
  97. $result = (is_array($var) ? self::serialize($var) : $var);
  98. $output = str_replace($match[0][$i], $result, $output);
  99. }
  100. return $output;
  101. }
  102. ////////////////////////////////////////////////////////////////////////////////
  103. function parse_lvars($output, $key, $value = null, $each = false){ if (is_array($output)) list($output, $key, $value, $each) = array($output['#text'], $output['#tag'], $key, $value);
  104. $output = str_replace('\%', self::char('%'), $output);
  105. $rand = rand();
  106. $pattern = '/%(\w+)?{'.preg_quote($key, '/').'(.([^}]*))?}/U';
  107. $replace = 'function.tags.parse_lvars.'.$key.'.'.$rand;
  108. if ($each){ $keys = array_keys($value);
  109. foreach ($keys as $k)
  110. $result .= preg_replace($pattern, '$\\1{'.$replace.'.'.$k.'\\2}', $output);
  111. $value[$keys[0]]['#is_first'] = true;
  112. $value[$k]['#is_last'] = true;
  113. } else {
  114. $result = preg_replace($pattern, '$\\1{'.$replace.'\\2}', $output);
  115. }
  116. self::vars($replace, $value);
  117. $result = self::parse($result);
  118. unset($GLOBALS['function']['tags']['parse_lvars'][$key][$rand]);
  119. return $result;
  120. }
  121. ////////////////////////////////////////////////////////////////////////////////
  122. protected function _values($values, $is_final = false){ $skipit = self::skip();
  123. foreach ($values as $it){
  124. $it['attributes']['#is_final'] = $is_final;
  125. $it['attributes']['#tag'] = self::ns($it['tag']);
  126. $it['attributes'] = array_change_key_case($it['attributes']);
  127. $it['attr'] = ($skip['tag'] ? $it['attributes'] : attr::normalize($it['attributes']));
  128. if (self::$ns){ $ns = str_replace(array(':', '-', '.'), '_', $it['tag']);
  129. if (
  130. !function_exists($func = 'tag_'.$it['attr']['#tag']) or
  131. substr($ns, 0, (strlen(self::$ns) + 1)) != self::$ns.'_'
  132. )
  133. unset($func);
  134. } elseif (!function_exists($func = 'tag_'.$it['attr']['#tag'])){
  135. unset($func);
  136. }
  137. if ($it['attr']['#skip'] and $it['attr']['#skip'] !== true)
  138. $result .= $it['attr']['#skip'];
  139. if ($skip['attr'] and $skip['attr']['level'] >= $it['level'] and ($it['type'] == 'open' or $it['type'] == 'complete'))
  140. unset($skip['attr']);
  141. if (!$skip['attr'] and $it['attr']['#skip'])
  142. $skip['attr'] = $it;
  143. if ($skip['attr'] and $skip['attr']['level'] <= $it['level'])
  144. continue;
  145. if ($skip['tag'] and $skip['tag']['level'] == $it['level'] and ($it['type'] == 'close' or $it['type'] == 'complete'))
  146. unset($skip['tag']);
  147. if (!$skip['tag'] and in_array($it['attr']['#tag'], $skipit) and $it['type'] == 'open')
  148. $skip['tag'] = $it;
  149. $result .= $it['attr']['#before'];
  150. if ((!$skip['tag'] or $skip['tag']['level'] >= $it['level']) and $func and ($it['type'] == 'open' or $it['type'] == 'complete')){
  151. $tmp[$it['tag']][$it['level']]['result'] = $result;
  152. $tmp[$it['tag']][$it['level']]['attr'] = $it['attr'];
  153. unset($result);
  154. }
  155. if (!$tmp[$it['tag']][$it['level']]){
  156. unset($attr);
  157. foreach ($it['attr'] as $k => $v)
  158. if ($k[0] != '#'){
  159. $quote = (is_int(strpos($v, '"')) ? "'" : '"');
  160. $attr .= ' '.$k.'='.$quote.$v.$quote;
  161. }
  162. if ($it['type'] == 'open' or ($it['type'] == 'complete' and ($it['value'] or self::is_container($it['attr']['#tag']))))
  163. $result .= '<'.$it['tag'].$attr.'>';
  164. elseif ($it['type'] == 'complete' and !$it['value'])
  165. $result .= '<'.$it['tag'].$attr.' />';
  166. $result .= $it['value'];
  167. if ($it['type'] == 'close' or ($it['type'] == 'complete' and ($it['value'] or self::is_container($it['attr']['#tag']))))
  168. $result .= '</'.$it['tag'].'>';
  169. } else {
  170. $result .= $it['value'];
  171. }
  172. if ($tmp[$it['tag']][$it['level']] and ($it['type'] == 'close' or $it['type'] == 'complete')){
  173. if ($result)
  174. $tmp[$it['tag']][$it['level']]['attr']['#text'] = $result;
  175. foreach ($tmp[$it['tag']][$it['level']]['attr'] as $k => $v)
  176. $tmp[$it['tag']][$it['level']]['attr'][$k] = self::unsux($v);
  177. $result = $tmp[$it['tag']][$it['level']]['result'];
  178. $result .= call_user_func($func, attr::normalize($tmp[$it['tag']][$it['level']]['attr'], false));
  179. unset($tmp[$it['tag']][$it['level']]);
  180. }
  181. $result .= $it['attr']['#after'];
  182. }
  183. return $result;
  184. }
  185. ////////////////////////////////////////////////////////////////////////////////
  186. function fill($tag, $attr = array()){
  187. if (is_array($tag)){
  188. $attr = $tag;
  189. $tag = $attr['#tag'];
  190. }
  191. $cont = (array_key_exists('#text', $attr) or self::is_container($tag));
  192. foreach ($attr as $k => $v)
  193. if (is_array($v))
  194. foreach ($v as $k2 => $v2){
  195. $attr[$k.'_'.$k2] = $v2;
  196. unset($attr[$k]);
  197. }
  198. foreach (attr::normalize($attr) as $k => $v){
  199. if ($k[0] != '#'){
  200. $quote = (is_int(strpos($v, '"')) ? "'" : '"');
  201. $attrs .= ' '.$k.'='.$quote.$v.$quote;
  202. }
  203. }
  204. $result = $attr['#before'].'<'.$tag.$attrs.(!$cont ? ' /' : '').'>';
  205. if ($cont)
  206. $result .= $attr['#text'].'</'.$tag.'>';
  207. $result .= $attr['#after'];
  208. return $result;
  209. }
  210. ////////////////////////////////////////////////////////////////////////////////
  211. function sux($output){
  212. $output = str_replace('&', self::char('&'), $output);
  213. $output = preg_replace('/\<([^a-z^\/])/ie', "str_replace('<', self::char('<'), '<\\1')", $output);
  214. return $output;
  215. }
  216. ////////////////////////////////////////////////////////////////////////////////
  217. function unsux($output){
  218. $output = str_replace(self::char('&'), '&', $output);
  219. $output = str_replace(self::char('$'), '$', $output);
  220. $output = str_replace(self::char('#'), '#', $output);
  221. $output = str_replace(self::char('@'), '@', $output);
  222. $output = str_replace(self::char('%'), '%', $output);
  223. $output = str_replace(self::char('<'), '<', $output);
  224. return $output;
  225. }
  226. ////////////////////////////////////////////////////////////////////////////////
  227. function html($string, $quote_style = ENT_QUOTES){ $string = htmlspecialchars_decode($string, $quote_style); $string = preg_replace(array('/&#35;(\w+?){/', '/&#36;(\w+?){/', '/&#37;(\w+?){/', '/&#64;(\w+?){/'), array('#\\1{', '$\\1{', '%\\1{', '@\\1{'), $string);
  228. return str_replace('&#96;', '`', $string);
  229. }
  230. ////////////////////////////////////////////////////////////////////////////////
  231. function unhtml($string, $quote_style = ENT_QUOTES){ $string = htmlspecialchars($string, $quote_style); $string = preg_replace(array('/#(\w+)?{/', '/\$(\w+)?{/', '/%(\w+)?{/', '/@(\w+)?{/'), array('&#35;\\1{', '&#36;\\1{', '&#37;\\1{', '&#64;\\1{'),$string);
  232. return str_replace('`', '&#96;', $string);
  233. }
  234. ////////////////////////////////////////////////////////////////////////////////
  235. function char($char){
  236. return '%it['.ord($char).']';
  237. }
  238. ////////////////////////////////////////////////////////////////////////////////
  239. function varname($string, $ns = ''){ static $array;
  240. if (!$ns)
  241. $ns = self::$var;
  242. if (isset($array[$ns][$string]))
  243. return $array[$ns][$string];
  244. $var = $string;
  245. $vars = array(
  246. '_get' => '_GET',
  247. '_post' => '_POST',
  248. '_files' => '_FILES',
  249. '_session' => '_SESSION',
  250. '_cookie' => '_COOKIE',
  251. '_server' => '_SERVER',
  252. );
  253. if (substr($var, 0, 8) == '_cookie.')
  254. $var = '_cookie.'.str_replace('.', '_', substr($var, 8));
  255. $var = str_replace('\.', self::char('.'), $var);
  256. $var = explode('.', $var);
  257. if ($vars[$var[0]])
  258. $var[0] = $vars[$var[0]];
  259. $var = $ns.($var ? "['".join("']['", $var)."']" : '');
  260. $var = str_replace("['']", '[]', $var);
  261. $var = str_replace(self::char('.'), '.', $var);
  262. return $array[$ns][$string] = $var;
  263. }
  264. ////////////////////////////////////////////////////////////////////////////////
  265. function vars(){ $args = func_get_args();
  266. $var = self::varname($args[0]);
  267. $name = explode('.', str_replace('\.', self::char('.'), $args[0]), 2);
  268. $map = array(
  269. '&' => '_ampersand_',
  270. '@' => '_at_',
  271. '*' => '_asterisk_',
  272. '^' => '_caret_',
  273. '#' => '_octothorp_',
  274. '$' => '_dollar_',
  275. '%' => '_percent_',
  276. '/' => '_slash_',
  277. '\\' => '_backslash_',
  278. self::char('.') => '_dot_'
  279. );
  280. if (function_exists($func = 'var_'.strtr($name[0], $map))){ $args[0] = substr($args[0], (strlen($name[0]) + 1));
  281. return call_user_func_array($func, $args);
  282. } elseif (func_num_args() == 2){
  283. if ($func = create_function('$def', 'return '.$var.' = $def;'))
  284. return $func($args[1]);
  285. } else {
  286. if ($func = create_function('', 'if (isset('.$var.')) return '.$var.';'))
  287. return $func();
  288. }
  289. }
  290. ////////////////////////////////////////////////////////////////////////////////
  291. function constant(){
  292. $args = func_get_args();
  293. if (func_num_args() == 2){
  294. if (!defined($args[0])){
  295. define($args[0], $args[1]);
  296. return constant($args[0]);
  297. }
  298. } else {
  299. if (defined($args[0]))
  300. return constant($args[0]);
  301. elseif (defined($args[0] = str_replace('.', '_', $args[0])))
  302. return constant($args[0]);
  303. }
  304. }
  305. ////////////////////////////////////////////////////////////////////////////////
  306. function elmname_parse($string){ if (!strpos($string, '['))
  307. return $string;
  308. $char = base64_encode(self::char('.'));
  309. $string = str_replace('.', $char, $string);
  310. $string = str_replace('][', '.', $string);
  311. $string = str_replace('[', '.', $string);
  312. $string = str_replace(']', '', $string);
  313. $string = str_replace($char, '\.', $string);
  314. return $string;
  315. }
  316. ////////////////////////////////////////////////////////////////////////////////
  317. function elmname_unparse($array){
  318. if (!is_array($array)){
  319. $array = str_replace('\.', self::char('.'), $array);
  320. $array = explode('.', $array);
  321. }
  322. $parent = array_shift($array);
  323. $string = $parent.($array ? '['.join('][', $array).']' : '');
  324. return str_replace(self::char('.'), '.', $string);
  325. }
  326. ////////////////////////////////////////////////////////////////////////////////
  327. function serialize($value){
  328. return base64_encode(serialize($value));
  329. }
  330. ////////////////////////////////////////////////////////////////////////////////
  331. function unserialize($value){
  332. $result = unserialize(base64_decode($value));
  333. return ($result ? $result : array());
  334. }
  335. ////////////////////////////////////////////////////////////////////////////////
  336. function is_array($value){
  337. return is_array(unserialize(base64_decode($value)));
  338. }
  339. ////////////////////////////////////////////////////////////////////////////////
  340. function is_container($tag = ''){
  341. static $tags;
  342. if (!$tags)
  343. $tags = array_flip(array(
  344. 'a',
  345. 'abbr',
  346. 'acronym',
  347. 'address',
  348. 'applet',
  349. 'b',
  350. 'bdo',
  351. 'bgsound',
  352. 'big',
  353. 'blink',
  354. 'blockquote',
  355. 'body',
  356. 'button',
  357. 'caption',
  358. 'center',
  359. 'cite',
  360. 'code',
  361. 'colgroup',
  362. 'comment',
  363. 'dd',
  364. 'del',
  365. 'dfn',
  366. 'dir',
  367. 'div',
  368. 'dl',
  369. 'dt',
  370. 'em',
  371. 'fieldset',
  372. 'font',
  373. 'form',
  374. 'frameset',
  375. 'h1',
  376. 'h2',
  377. 'h3',
  378. 'h4',
  379. 'head',
  380. 'html',
  381. 'i',
  382. 'iframe',
  383. 'ilayer',
  384. 'ins',
  385. 'kbd',
  386. 'label',
  387. 'layer',
  388. 'legend',
  389. //'li',
  390. 'listing',
  391. 'map',
  392. 'marquee',
  393. 'menu',
  394. 'multicol',
  395. 'nobr',
  396. 'noembed',
  397. 'noframes',
  398. 'nolayer',
  399. 'noscript',
  400. 'object',
  401. 'ol',
  402. //'optgroup',
  403. 'option',
  404. //'p',
  405. 'plaintext',
  406. 'pre',
  407. 'q',
  408. 'rb',
  409. 'rbc',
  410. 'rp',
  411. 'rt',
  412. 'ruby',
  413. 's',
  414. 'samp',
  415. 'script',
  416. 'select',
  417. 'small',
  418. 'span',
  419. 'strike',
  420. 'strong',
  421. 'style',
  422. 'sub',
  423. 'sup',
  424. 'table',
  425. 'tbody',
  426. //'td',
  427. 'textarea',
  428. 'tfoot',
  429. //'th',
  430. 'thead',
  431. 'title',
  432. //'tr',
  433. 'tt',
  434. 'u',
  435. 'ul',
  436. 'var',
  437. 'xml',
  438. 'xmp',
  439. 'noindex',
  440. 'berry'
  441. ));
  442. return ($tag ? is_int($tags[$tag]) : $tags);
  443. }
  444. ////////////////////////////////////////////////////////////////////////////////
  445. function parse_supadupa($output, $is_final = false){ static $tags;
  446. if (!$tags){ $ns = (self::$ns ? self::$ns.'_' : '');
  447. $tags = str_replace('_', '[_\.:-]', $ns.join('|'.$ns, array_keys(self::functions('supadupa'))));
  448. }
  449. if (preg_match_all('/<('.$tags.')( ([^>]*))?>(.*?)<\/\\1>/isU', $output, $match))
  450. for ($i = 0, $c = count($match[0]); $i < $c; $i++){ $attr = array('#tag' => self::ns($match[1][$i]), '#is_final' => $is_final); $match[2][$i] = self::parse_vars($match[2][$i]);
  451. if (preg_match_all('/ ([\w\.:-]+)=("|\')(.*?)\\2/is', $match[2][$i], $match2)){
  452. for ($i2 = 0, $c2 = count($match2[0]); $i2 < $c2; $i2++)
  453. $match2[1][$i2] = strtolower(str_replace(array(':', '-', '.'), '_', $match2[1][$i2]));
  454. $attr = array_merge($attr, array_combine($match2[1], $match2[3]));
  455. $attr = attr::normalize($attr);
  456. }
  457. if ($attr['#skip']){
  458. if ($attr['#skip'] !== true)
  459. $output = str_replace($match[0][$i], $attr['#skip'], $output);
  460. } else { $attr['#text'] = $match[4][$i];
  461. $output = str_replace($match[0][$i], call_user_func('supadupa_'.$attr['#tag'], $attr), $output);
  462. }
  463. }
  464. return $output;
  465. }
  466. ////////////////////////////////////////////////////////////////////////////////
  467. function functions($prefix = ''){
  468. if (!$prefix)
  469. return end(get_defined_functions());
  470. $funcs = end(get_defined_functions());
  471. $len = (strlen($prefix) + 1);
  472. foreach ($funcs as $func)
  473. if (substr($func, 0, $len) == $prefix.'_')
  474. if ($func = substr($func, $len))
  475. $result[$func] = $prefix.'_'.$func;
  476. return ($result ? $result : array());
  477. }
  478. ////////////////////////////////////////////////////////////////////////////////
  479. function constants($prefix = ''){
  480. if (!$prefix)
  481. return array_keys(get_defined_constants());
  482. $consts = array_keys(get_defined_constants());
  483. $len = (strlen($prefix) + 1);
  484. foreach ($consts as $const)
  485. if (substr($const, 0, $len) == $prefix.'_')
  486. if ($const = substr($const, $len))
  487. $result[$const] = $prefix.'_'.$const;
  488. return ($result ? $result : array());
  489. }
  490. ////////////////////////////////////////////////////////////////////////////////
  491. function ns($tag){ $tag = strtolower(str_replace(array(':', '-', '.'), '_', $tag));
  492. if (!self::$ns)
  493. return $tag;
  494. $ns = (strlen(self::$ns) + 1);
  495. if (substr($tag, 0, $ns) == self::$ns.'_')
  496. return substr($tag, $ns);
  497. return $tag;
  498. }
  499. ////////////////////////////////////////////////////////////////////////////////
  500. }