PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/ xvweb/core/libraries/parser.MyHTML.XVweb.class.php

http://xvweb.googlecode.com/
PHP | 411 lines | 329 code | 42 blank | 40 comment | 45 complexity | 05f892cf41810dbaf5e00443b83270cf MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, LGPL-3.0
  1. <?php
  2. class ParserMyHTML
  3. {
  4. /************************************************************************************************/
  5. const Version = "1.0";
  6. /************************************************************************************************/
  7. public $allowedTags = '<h1><h><h2><h3><h4><h5><h6><b><i><a><ul><li><pre><hr><blockquote><img><table><br><button><caption><center><cite><var><code><del><col><colgroup><dd><dl><em><form><input><ins><kbd><label><p><sup><sub><tbody><td><textarea><tfoot><th><thead><tr><tt><u><var><span><strong><font><strike><s><ol><fieldset><legend><nobr><div><php><delphi><cpp><java><java5><css><javascript><code><nohtml><include><vars><file><small>';
  8. public $stripAttrib = 'javascript:|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup|onload|onblur|onchange|onfocus|onselect|onsubmit|onunload|absolute|fixed|expression';
  9. public $text;
  10. /************************************************************************************************/
  11. public $SpecialChars= false;
  12. public $Date=array();
  13. public $SupportedTags= array("include","php", "delphi","cpp","java","java5","css","javascript", "code", "vars", "file", "[file]", "nohtml", "nobr");
  14. public $EmotArray = '';
  15. /************************************************************************************************/
  16. var $pattern = array(
  17. "u" =>"<span style=\"text-decoration:underline;\">{match}</span>",
  18. "b" =>"<span style=\"font-weight: bold;\">{match}</span>",
  19. "i" =>"<span style=\"font-style: italic;\">{match}</span>",
  20. "s" =>"<span style=\"text-decoration: line-through;\">{match}</span>",
  21. "strike" =>"<span style=\"text-decoration: line-through;\">{match}</span>",
  22. "left" =>"<span style=\"text-align: left;\">{match}</span>",
  23. "center" =>"<span style=\"text-align: center;\">{match}</span>",
  24. "right" =>"<span style=\"text-align: right;\">{match}</span>",
  25. "justify" =>"<span style=\"text-align: justify;\">{match}</span>"
  26. );
  27. /************************************************************************************************/
  28. public function __construct(&$XVweb) {
  29. $this->Date['XVweb']= &$XVweb;
  30. $this->Date['Randomize']= rand();
  31. $this->Date['XVweb']->Date['EngineVars'] = array_merge_recursive((is_array($this->Date['XVweb']->Date['EngineVars'])?$this->Date['XVweb']->Date['EngineVars'] : array()),array(
  32. "{{version}}"=> constant(get_class($this->Date['XVweb']).'::Version'),
  33. "{{phpversion}}"=> phpversion(),
  34. "{{phpos}}"=> PHP_OS,
  35. "{{artver}}"=> (isset($this->Date['XVweb']->ReadArticleOut['Version']) ? $this->Date['XVweb']->ReadArticleOut['Version'] : "13"),
  36. "{{artid}}"=> (isset($this->Date['XVweb']->ReadArticleIndexOut['ID']) ? $this->Date['XVweb']->ReadArticleIndexOut['ID'] : "11"),
  37. "{{arttotalvotes}}"=> (isset($this->Date['XVweb']->ReadArticleIndexOut['AllVotes']) ? $this->Date['XVweb']->ReadArticleIndexOut['AllVotes'] : "0"),
  38. "{{average}}"=> (isset($this->Date['XVweb']->ReadArticleIndexOut['Votes']) ? $this->Date['XVweb']->ReadArticleIndexOut['Votes'] : "0"),
  39. "{{artdate}}"=> (isset($this->Date['XVweb']->ReadArticleIndexOut['Data']) ? $this->Date['XVweb']->ReadArticleIndexOut['Data'] : "0000-00-00 00:00:00"),
  40. "{{artverdate}}"=> (isset($this->Date['XVweb']->ReadArticleOut['Date']) ? $this->Date['XVweb']->ReadArticleOut['Date'] : "0000-00-00 00:00:00"),
  41. "{{artauthor}}"=> (isset($this->Date['XVweb']->ReadArticleOut['Author']) ? $this->Date['XVweb']->ReadArticleOut['Author'] : "User"),
  42. "{{counter}}"=> (isset($this->Date['XVweb']->ReadArticleIndexOut['Views']) ? $this->Date['XVweb']->ReadArticleIndexOut['Views'] : 0),
  43. "{{parserversion}}"=> constant(get_class($this->Date['XVweb']).'::Version'),
  44. "{{descriptionofchange}}"=> (isset($this->Date['XVweb']->ReadArticleOut['DescriptionOfChange']) ? $this->Date['XVweb']->ReadArticleOut['DescriptionOfChange'] : "None"),
  45. "{{artverid}}"=> (isset($this->Date['XVweb']->ReadArticleOut['ID']) ? $this->Date['XVweb']->ReadArticleOut['ID'] : 1)
  46. ));
  47. if(is_array($this->Date['XVweb']->Date['EngineFunctions'])){
  48. foreach($this->Date['XVweb']->Date['EngineFunctions'] as $PLGFunction){
  49. $this->SupportedTags[] = $PLGFunction['Tag'];
  50. $this->allowedTags .= '<'.$PLGFunction['Tag'].'>';
  51. $this->Date['TagsFunctions'][strtolower($PLGFunction['Tag'])] = $PLGFunction;
  52. }
  53. }
  54. $GLOBALS['Debug']['Classes'][] = array("ClassName"=>get_class(), "File"=>__FILE__, "Time"=>microtime(true), "MemoryUsage"=>memory_get_usage());
  55. }
  56. /************************************************************************************************/
  57. function RepairTidy($html) {
  58. return $html;
  59. if(extension_loaded('tidy' )){
  60. $returned = tidy_repair_string($html, array("show-body-only"=>true, "output-xhtml"=>true), 'UTF8');
  61. return $returned;
  62. }
  63. preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
  64. $openedtags = $result[1];
  65. preg_match_all('#</([a-z]+)>#iU', $html, $result);
  66. $closedtags = $result[1];
  67. $len_opened = count($openedtags);
  68. if (count($closedtags) == $len_opened) {
  69. return $html;
  70. }
  71. $openedtags = array_reverse($openedtags);
  72. for ($i=0; $i < $len_opened; ++$i) {
  73. if (!in_array($openedtags[$i], $closedtags) && (strpos($this->allowedTags, '<'.$openedtags[$i].'>') !==false)){
  74. $html .= '</'.$openedtags[$i].'>';
  75. } else {
  76. unset($closedtags[array_search($openedtags[$i], $closedtags)]);
  77. }
  78. }
  79. return $html;
  80. }
  81. /************************************************************************************************/
  82. function OldHtmlToXHTMLFoo($match) {
  83. if(isset($this->pattern[strtolower($match[1])]))
  84. return str_replace("{match}", $match[0], $this->pattern[strtolower($match[1])]);
  85. return $match[0];
  86. }
  87. /************************************************************************************************/
  88. function OldHtmlToXHTML($html) {
  89. return preg_replace_callback('/<(u|b|i|s|strike|left|center|right|justify)>(.+?)<\/(u|b|i|s|strike|left|center|right|justify)>/si', array($this, "OldHtmlToXHTMLFoo"), $html);
  90. }
  91. /************************************************************************************************/
  92. function strip_tags_except($text, $allowed_tagsHTML, $strip=false) {
  93. if (is_array($allowed_tagsHTML)){
  94. $allowed_tags = $allowed_tagsHTML;
  95. }else{
  96. $pattern = '/<(.+?)>/si';
  97. preg_match_all($pattern, $allowed_tagsHTML, $matches);
  98. $allowed_tags = $matches[1];
  99. }
  100. $open = $strip ? '' : '&lt;';
  101. $close = $strip ? '' : '&gt;';
  102. preg_match_all('!<\s*(/)?\s*([a-zA-Z]+)[^>]*>!',
  103. $text, $all_tags);
  104. array_shift($all_tags);
  105. $slashes = $all_tags[0];
  106. $all_tags = $all_tags[1];
  107. foreach ($all_tags as $i => $tag) {
  108. if (in_array($tag, $allowed_tags))
  109. continue;
  110. $text =
  111. preg_replace('!<(\s*' . $slashes[$i] . '\s*' .
  112. $tag . '[^>]*)>!', $open . '$1' . $close,
  113. $text);
  114. }
  115. return $text;
  116. }
  117. /************************************************************************************************/
  118. function PluginFunctions(&$element)
  119. {
  120. if(isset($this->Date['TagsFunctions'][$element->tag]['Function']))
  121. eval($this->Date['TagsFunctions'][$element->tag]['Function']);
  122. }
  123. /************************************************************************************************/
  124. function ChangeEmot($co="", $naco="")
  125. {
  126. $co = stripslashes($co);
  127. return ' <img src="'.$naco.'" title="'.htmlspecialchars($co).'" alt="'.htmlspecialchars($co).'" border="0" /> ';
  128. }
  129. /************************************************************************************************/
  130. function removeEvilTags($source)
  131. {
  132. $allowedTagsLocal = $this->allowedTags;
  133. $source = $this->strip_tags_except($source, $allowedTagsLocal);
  134. return preg_replace('/<(.*?)>/ie', "'<'.\$this->removeEvilAttributes('\\1').'>'", $source);
  135. }
  136. /************************************************************************************************/
  137. function removeEvilAttributes($tagSource)
  138. {
  139. $stripAttribs = $this->stripAttrib;
  140. return stripslashes(preg_replace("/$stripAttribs/i", 'forbidden', $tagSource));
  141. }
  142. /************************************************************************************************/
  143. function hide_mail($mail)
  144. {
  145. $ReturnVar = explode("@", $mail[2]);
  146. $ReturnVar = $mail[1]."
  147. <script type=\"text/javascript\">
  148. var d='".$ReturnVar[1]."', m='@', s= \"".$ReturnVar[0]."\";
  149. document.write('<a href=\"mailto:'+s+m+d+'\">'+s+m+d+'</a>');
  150. </script>
  151. ";
  152. return $ReturnVar;
  153. }
  154. /************************************************************************************************/
  155. function cut_url($url)
  156. {
  157. $url_len = strlen($url);
  158. if ( $url_len > 50)
  159. $url = substr($url, 0, 20) . '[...]' . substr($url, $url_len - 20, 20);
  160. return $url;
  161. }
  162. /************************************************************************************************/
  163. function hyperlink($string)
  164. {
  165. $patterns[] = '#(?:^|(?<=[][()<>\s]|&gt;|&lt;))(\w+:/{2}.*?(?:[^][ \t\n\r<>")&,\']+|&(?!lt;|gt;)|,(?!\s)|\[])*)#ie';
  166. $replacements[] = "'<a href=\"$1\">' . cut_url('$1', 70) . '</a>'";
  167. $patterns[] = '#(?:^|(?<=[][()<>"\'\s]|&gt;|&lt;))(w{3}\.[\w-]+\.[\w.~-]+(?:[^][ \t\n\r<>")&,\']+|&(?!lt;|gt;)|,(?!\s)|\[])*)#ie';
  168. $replacements[] = "'<a href=\"http://$1\">' . cut_url('$1', 70) . '</a>'";
  169. $string = preg_replace_callback('#(^|[\n ]|\()([a-z0-9&\-_.]+?@[\w\-]+\.(?:[\w\-\.]+\.)?[\w]+)#i',
  170. array($this, "hide_mail"), $string);
  171. $string = preg_replace($patterns, $replacements, $string);
  172. return $string;
  173. }
  174. /************************************************************************************************/
  175. function EngineVars(&$element){
  176. echo pq($element)->attr("value");
  177. exit;
  178. if(!is_null(pq($element)->attr("value")))
  179. $varName = pq($element)->attr("value");
  180. elseif(!is_null(pq($element)->html()))
  181. $varName = pq($element)->html();
  182. pq($element)->replaceWith((isset($this->Date['XVweb']->Date['EngineVars']['{{'.$varName.'}}']) ? $this->Date['XVweb']->Date['EngineVars']['{{'.$varName.'}}'] : ""));
  183. return "";
  184. }
  185. /************************************************************************************************/
  186. public function CommentParse($string){
  187. $this->Date['Options']['EnablePHP'] = 0;
  188. $this->Date['Options']['EnableHTML'] = 0;
  189. return $this->SetText($string)->Parse()->ToHTML();
  190. }
  191. /************************************************************************************************/
  192. public function &set($name, $value){
  193. $this->Date[$name] = $value;
  194. return $this;
  195. }
  196. /************************************************************************************************/
  197. function GetIncludeArticle(&$Properies){
  198. if($this->Date['GIACounter']>20 or !ifsetor($this->Date['Options']['IncludeArticle'], true))
  199. return "";
  200. $this->Date['GIACounter'] += 1;
  201. $ReplaceVars = array();
  202. foreach(pq($Properies)->attr("*") as $key=>$value)
  203. $ReplaceVars['{{var:'.$key.'}}'] = $value;
  204. pq($Properies)->replaceWith(strtr($this->Date['XVweb']->GetOnlyContextArticle(trim(pq($Properies)->html())),$ReplaceVars));
  205. }
  206. /************************************************************************************************/
  207. function GetFile(&$element){
  208. if($this->Date['GFCounter'] > 100 or ifsetor($this->Date['Options']['DisableFiles'], false)){
  209. pq($element)->replaceWith("");
  210. return "";
  211. }
  212. $this->Date['GFCounter'] += 1;
  213. if(!is_null(pq($element)->attr("id")))
  214. $FileID = pq($element)->attr("id"); // Pobieranie ID pliku
  215. if(!is_null(pq($element)->attr("file")))
  216. $FileID= pq($element)->attr("file"); // pobieranie ID pliku z attrybutu file
  217. //pq($element)->removeAttr("file");
  218. $FileID = trim($FileID);
  219. if(!is_null(pq($element)->attr("replace")))
  220. $ReplaceTo = pq($element)->attr("replace"); // z czym zamieni?
  221. pq($element)->removeAttr("replace"); // usuniecie niepotrzebnego atrybutu
  222. if(!is_numeric($FileID)){
  223. pq($element)->replaceWith("Invalid ID File"); // Z?y ID pliku
  224. return;
  225. }
  226. if(!isset($this->Date['File'][$FileID])){ // sprawdzanie czy dany plik istnieje w cache
  227. $this->Date['File'][$FileID] = $this->Date['XVweb']->FilesClass()->GetFile($FileID);
  228. $this->Date['File'][$FileID]['FileSize'] = $this->Date['XVweb']->Date['FilesClass']->size_comp($this->Date['File'][$FileID]['FileSize']);
  229. }
  230. $File = &$this->Date['File'][$FileID];
  231. //Generowanie info o pliku
  232. $File['Link'] = $this->Date['XVweb']->Date['UrlSite'].'File/'.$File['ID'].'/'.$File['FileName'].(empty($File['Extension']) ? '': '.'.$File['Extension']);
  233. $File['HTMLLink'] = "<a href='".$this->Date['XVweb']->Date['UrlSite'].'File/'.$File['ID'].'/'.$File['FileName'].(empty($File['Extension']) ? '': '.'.$File['Extension'])."'>".$File['FileName'].(empty($File['Extension']) ? '': '.'.$File['Extension']).'</a>';
  234. $File['Name'] = $File['FileName'].(empty($File['Extension']) ? '': '.'.$File['Extension']);
  235. if($File['Extension'] == "zip")
  236. $File['StructureZIP'] = htmlspecialchars($this->Date['XVweb']->Date['FilesClass']->GetStructureZIP($GLOBALS['UploadDir'].$File['MD5File'].$File['SHA1File']));
  237. if(isset($FileID)){
  238. if(is_null(pq($element)->attr("get"))){
  239. pq($element)->attr("get", "Link"); // Jesli nie ma parametru get, to pobierz default: link
  240. if($element->tagName =="file")
  241. pq($element)->attr("get", "HTMLLink");
  242. }
  243. if(!is_null(pq($element)->attr("file")) or pq($element)->attr("id") === true){
  244. if(empty($ReplaceTo)){
  245. pq($element)->replaceWith((isset($File[pq($element)->attr("get")]) ? $File[pq($element)->attr("get")] : ""));
  246. } else{
  247. $ReplaceWith = $ReplaceTo;
  248. $ReplaceWTo = (isset($File[pq($element)->attr("get")]) ? $File[pq($element)->attr("get")] : "1");
  249. pq($element)->replaceWith(str_replace(array($ReplaceWith, $this->encode_full_url($ReplaceWith)), $ReplaceWTo, pq($element)->htmlOuter()));
  250. /* foreach(pq($element)->attr("*") as $keyattr=>$valattr){
  251. pq($element)->attr($keyattr,
  252. str_replace(
  253. (!empty($ReplaceTo) ? $ReplaceTo : '{{get}}'), // 1
  254. (isset($File[pq($element)->attr("get")]) ? $File[pq($element)->attr("get")] : ""), // 2
  255. $valattr // 3
  256. )
  257. ) ;
  258. }*/
  259. }
  260. return "";
  261. }
  262. if(!is_null(pq($element)->attr("get"))){
  263. $TOGet = pq($element)->attr("get");
  264. pq($element)->removeAttr("get");
  265. if(isset($File[$TOGet]))
  266. $TOGet = $File[$TOGet];
  267. else
  268. $TOGet = "";
  269. pq($element)->replaceWith($TOGet);
  270. return "";
  271. }
  272. }
  273. pq($element)->replaceWith("<a href='".$this->Date['XVweb']->Date['UrlSite'].'File/'.$File['ID'].'/'.$File['FileName'].(empty($File['Extension']) ? '': '.'.$File['Extension'])."'>".$File['FileName'].(empty($File['Extension']) ? '': '.'.$File['Extension']).'</a>');
  274. return;
  275. }
  276. /************************************************************************************************/
  277. function &Geshi(){
  278. if(empty($this->Date['Geshi'])){
  279. include_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'geshi.php');
  280. $this->Date['Geshi'] = new GeSHi();
  281. $this->Date['Geshi']->set_encoding("utf-8");
  282. }
  283. return $this->Date['Geshi'];
  284. }
  285. /************************************************************************************************/
  286. public function GeshiText($Code, $Lang){
  287. if(ifsetor($this->Date['Options']['DisableGeshi'], false))
  288. return $Code;
  289. $this->Geshi()->set_source($Code);
  290. $this->Geshi()->set_language($Lang);
  291. return $this->Geshi()->parse_code();
  292. }
  293. /************************************************************************************************/
  294. public function &SetText($text){
  295. if(ifsetor($this->Date['Options']['DisableParser'], false)){
  296. $this->text = ($text);
  297. return $this;
  298. }
  299. $this->text = phpQuery::newDocumentPHP($text);
  300. foreach($this->text['include'] as $element)
  301. $this->GetIncludeArticle($element);
  302. return $this;
  303. }
  304. /************************************************************************************************/
  305. public function &Parse(){
  306. if(ifsetor($this->Date['Options']['DisableParser'], false)){
  307. return $this;
  308. }
  309. foreach($this->text['nohtml'] as $element){
  310. pq($element)->replaceWith(htmlspecialchars(pq($element)->html()));
  311. }
  312. foreach($this->text['nobr'] as $element){
  313. if(is_null(pq($element)->attr("all"))){
  314. pq($element)->replaceWith(str_replace(chr(13), 'bs'.($this->Date['Randomize']), pq($element)->html()));
  315. }else{
  316. $this->Date['Options']['DisableBreakLine'] = 1;
  317. pq($element)->replaceWith(pq($element)->html());
  318. }
  319. }
  320. foreach($this->text['info'] as $element){
  321. if(!is_null(pq($element)->attr("hidden")) && pq($element)->attr("hidden") == "true"){
  322. pq($element)->replaceWith("");
  323. }else{
  324. pq($element)->replaceWith(pq($element)->html());
  325. }
  326. }
  327. foreach($this->text['include'] as $element)
  328. $this->GetIncludeArticle($element);
  329. foreach($this->text['vars'] as $element)
  330. $this->EngineVars($element);
  331. foreach($this->text['file, *[file]'] as $element)
  332. $this->GetFile($element);
  333. foreach($this->text['code, php, delphi, cpp, java, java5, javascript, css'] as $element){
  334. pq($element)->replaceWith($this->GeshiText( pq($element)->php() , (strtolower($element->tagName) == "code" ? pq($element)->attr('lang') : $element->tagName)));
  335. }
  336. if(isset($this->Date['TagsFunctions']) && is_array($this->Date['TagsFunctions'])){
  337. foreach($this->Date['TagsFunctions'] as $PLGTag){
  338. foreach($this->text[$PLGTag['Tag']] as $element)
  339. eval($PLGTag['Function']);
  340. }
  341. }
  342. $this->text = $this->text->php();
  343. if(!(ifsetor($this->Date['Options']['EnableHTML'], 0) or ifsetor($this->Date['EnableHTML'], 0)))
  344. $this->text = $this->removeEvilTags($this->text);
  345. if(!ifsetor($this->Date['Options']['DisableBreakLine'], 0)){
  346. //$this->Date['XVweb']->Date['EngineVars']["\n"] = '<br />'; // test mode
  347. }
  348. $this->Date['XVweb']->Date['EngineVars']['s'.($this->Date['Randomize'])] = '<';
  349. $this->Date['XVweb']->Date['EngineVars']['e'.($this->Date['Randomize'])] = '>';
  350. $this->Date['XVweb']->Date['EngineVars']['bs'.($this->Date['Randomize'])] = chr(13);
  351. $this->text = strtr($this->text, $this->Date['XVweb']->Date['EngineVars']);
  352. if(!ifsetor($this->Date['Options']['EnablePHP'], 0))
  353. $this->text = $this->RepairTidy($this->text);
  354. return $this;
  355. }
  356. /************************************************************************************************/
  357. public function ToHTML(){
  358. return $this->text;
  359. }
  360. /************************************************************************************************/
  361. public function encode_full_url(&$url) {
  362. $url = urlencode($url);
  363. $url = str_replace("%2F", "/", $url);
  364. $url = str_replace("%3A", ":", $url);
  365. return $url;
  366. }
  367. }
  368. ?>