84 $i++; |
84 $i++; |
85 } |
85 } |
86 // List out all CSS files for this theme |
86 // List out all CSS files for this theme |
87 foreach ( $this->theme_list as $i => &$theme ) |
87 foreach ( $this->theme_list as $i => &$theme ) |
88 { |
88 { |
89 $theme['css'] = array(); |
89 $theme['css'] = $this->get_theme_css_files($theme['theme_id']); |
90 $dir = ENANO_ROOT . "/themes/{$theme['theme_id']}/css"; |
90 } |
91 if ( $dh = @opendir($dir) ) |
91 unset($theme); |
92 { |
|
93 while ( ( $file = @readdir($dh) ) !== false ) |
|
94 { |
|
95 if ( preg_match('/\.css$/', $file) ) |
|
96 $theme['css'][] = preg_replace('/\.css$/', '', $file); |
|
97 } |
|
98 closedir($dh); |
|
99 } |
|
100 // No CSS files? If so, nuke it. |
|
101 if ( count($theme['css']) < 1 ) |
|
102 { |
|
103 unset($this->theme_list[$i]); |
|
104 } |
|
105 } |
|
106 $this->theme_list = array_values($this->theme_list); |
92 $this->theme_list = array_values($this->theme_list); |
107 // Create associative array of themes |
93 // Create associative array of themes |
108 foreach ( $this->theme_list as $i => &$theme ) |
94 foreach ( $this->theme_list as $i => &$theme ) |
109 $this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i]; |
95 $this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i]; |
110 |
96 |
111 $this->default_theme = ( $_ = getConfig('theme_default') ) ? $_ : $this->theme_list[0]['theme_id']; |
97 $this->default_theme = ( $_ = getConfig('theme_default') ) ? $_ : $this->theme_list[0]['theme_id']; |
112 // Come up with the default style. If the CSS file specified in default_style exists, we're good, just |
98 // Come up with the default style. If the CSS file specified in default_style exists, we're good, just |
113 // use that. Otherwise, use the first stylesheet that comes to mind. |
99 // use that. Otherwise, use the first stylesheet that comes to mind. |
114 $df_data =& $this->named_theme_list[ $this->default_theme ]; |
100 $df_data =& $this->named_theme_list[ $this->default_theme ]; |
115 $this->default_style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0]; |
101 $this->default_style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0]; |
|
102 } |
|
103 |
|
104 /** |
|
105 * Gets the list of available CSS files (styles) for the specified theme. |
|
106 * @param string Theme ID |
|
107 * @return array |
|
108 */ |
|
109 |
|
110 function get_theme_css_files($theme_id) |
|
111 { |
|
112 $css = array(); |
|
113 $dir = ENANO_ROOT . "/themes/{$theme_id}/css"; |
|
114 if ( $dh = @opendir($dir) ) |
|
115 { |
|
116 while ( ( $file = @readdir($dh) ) !== false ) |
|
117 { |
|
118 if ( preg_match('/\.css$/', $file) ) |
|
119 $css[] = preg_replace('/\.css$/', '', $file); |
|
120 } |
|
121 closedir($dh); |
|
122 } |
|
123 // No CSS files? If so, nuke it. |
|
124 if ( count($css) < 1 ) |
|
125 { |
|
126 unset($this->theme_list[$theme_id]); |
|
127 } |
|
128 return $css; |
116 } |
129 } |
117 |
130 |
118 /** |
131 /** |
119 * Failsafe constructor for upgrades. |
132 * Failsafe constructor for upgrades. |
120 */ |
133 */ |
1473 <b>Theme currently in use: </b>' . $this->theme . '<br /> |
1502 <b>Theme currently in use: </b>' . $this->theme . '<br /> |
1474 <b>Requested file: </b>' . $file . ' |
1503 <b>Requested file: </b>' . $file . ' |
1475 </p>'); |
1504 </p>'); |
1476 } |
1505 } |
1477 |
1506 |
1478 // Check for cached copy |
1507 // We won't use the cached copy here. |
1479 // This will make filenames in the pattern of theme-file.tpl.php |
|
1480 $cache_file = ENANO_ROOT . '/cache/' . $this->theme . '-' . str_replace('/', '-', $filename) . '.php'; |
|
1481 |
|
1482 // Only use cached copy if caching is enabled |
|
1483 // (it is enabled by default I think) |
|
1484 if ( file_exists($cache_file) && getConfig('cache_thumbs') == '1' ) |
|
1485 { |
|
1486 // Cache files are auto-generated, but otherwise are normal PHP files |
|
1487 include($cache_file); |
|
1488 |
|
1489 // Fetch content of the ORIGINAL |
|
1490 $text = file_get_contents($tpl_file_fullpath); |
|
1491 |
|
1492 // $md5 will be set by the cached file |
|
1493 // This makes sure that a cached copy of the template is used only if its MD5 |
|
1494 // matches the MD5 of the file that the compiled file was compiled from. |
|
1495 if ( isset($md5) && $md5 == md5($text) ) |
|
1496 { |
|
1497 return $this->compile_template_text_post(str_replace('\\"', '"', $tpl_text)); |
|
1498 } |
|
1499 } |
|
1500 |
|
1501 // We won't use the cached copy here |
|
1502 $text = file_get_contents($tpl_file_fullpath); |
1508 $text = file_get_contents($tpl_file_fullpath); |
1503 |
1509 |
1504 // This will be used later when writing the cached file |
1510 // This will be used later when writing the cached file |
1505 $md5 = md5($text); |
1511 $md5 = md5($text); |
1506 |
1512 |
1507 // Preprocessing and checks complete - compile the code |
1513 // Preprocessing and checks complete - compile the code |
1508 $text = $this->compile_tpl_code($text); |
1514 $text = $this->compile_tpl_code($text); |
1509 |
1515 |
|
1516 // Generate cache filename |
|
1517 $cache_file = ENANO_ROOT . '/cache/' . $this->theme . '-' . str_replace('/', '-', $filename) . '.php'; |
|
1518 |
1510 // Perhaps caching is enabled and the admin has changed the template? |
1519 // Perhaps caching is enabled and the admin has changed the template? |
1511 if ( is_writable( ENANO_ROOT . '/cache/' ) && getConfig('cache_thumbs') == '1' ) |
1520 if ( is_writable( ENANO_ROOT . '/cache/' ) && getConfig('cache_thumbs') == '1' ) |
1512 { |
1521 { |
1513 $h = fopen($cache_file, 'w'); |
1522 $h = fopen($cache_file, 'w'); |
1514 if ( !$h ) |
1523 if ( !$h ) |
1515 { |
1524 { |
1516 // Couldn't open the file - silently ignore and return |
1525 // Couldn't open the file - silently ignore and return |
1517 return $text; |
1526 return $text; |
1518 } |
1527 } |
1519 |
1528 |
1520 // Escape the compiled code so it can be eval'ed |
1529 // Final contents of cache file |
1521 $text_escaped = addslashes($text); |
1530 $file_contents = <<<EOF |
1522 $notice = <<<EOF |
1531 <?php |
1523 |
1532 |
1524 /* |
1533 /* |
1525 * NOTE: This file was automatically generated by Enano and is based on compiled code. Do not edit this file. |
1534 * NOTE: This file was automatically generated by Enano and is based on compiled code. Do not edit this file. |
1526 * If you edit this file, any changes you make will be lost the next time the associated source template file is edited. |
1535 * If you edit this file, any changes you make will be lost the next time the associated source template file is edited. |
1527 */ |
1536 */ |
1528 |
1537 |
|
1538 \$md5 = '$md5'; |
|
1539 |
|
1540 $text |
1529 EOF; |
1541 EOF; |
1530 // This is really just a normal PHP file that sets a variable or two and exits. |
1542 // This is really just a normal PHP file that sets a variable or two and exits. |
1531 // $tpl_text actually will contain the compiled code |
1543 // $tpl_text actually will contain the compiled code |
1532 fwrite($h, '<?php ' . $notice . ' $md5 = \'' . $md5 . '\'; $tpl_text = \'' . $text_escaped . '\'; ?>'); |
1544 fwrite($h, $file_contents); |
1533 fclose($h); |
1545 fclose($h); |
1534 } |
1546 } |
1535 |
1547 |
1536 return $this->compile_template_text_post($text); //('<pre>'.htmlspecialchars($text).'</pre>'); |
1548 return $this->compile_template_text_post($text); //('<pre>'.htmlspecialchars($text).'</pre>'); |
1537 } |
1549 } |
1634 $message = str_replace('$'.$links[$i].'$', $this->tpl_strings[$links[$i]], $message); |
1666 $message = str_replace('$'.$links[$i].'$', $this->tpl_strings[$links[$i]], $message); |
1635 } |
1667 } |
1636 |
1668 |
1637 // Conditionals |
1669 // Conditionals |
1638 |
1670 |
1639 preg_match_all('#\{if ([A-Za-z0-9_ \(\)&\|\!-]*)\}(.*?)\{\/if\}#is', $message, $links); |
1671 $message = $this->twf_parse_conditionals($message); |
1640 |
|
1641 // Temporary exception from coding standards - using tab length of 4 here for clarity |
|
1642 for ( $i = 0; $i < sizeof($links[1]); $i++ ) |
|
1643 { |
|
1644 $condition =& $links[1][$i]; |
|
1645 $message = str_replace('{if '.$condition.'}'.$links[2][$i].'{/if}', '{CONDITIONAL:'.$i.':'.$random_id.'}', $message); |
|
1646 |
|
1647 // Time for some manual parsing... |
|
1648 $chk = false; |
|
1649 $current_id = ''; |
|
1650 $prn_level = 0; |
|
1651 // Used to keep track of where we are in the conditional |
|
1652 // Object of the game: turn {if this && ( that OR !something_else )} ... {/if} into if( ( isset($this->tpl_bool['that']) && $this->tpl_bool['that'] ) && ... |
|
1653 // Method of attack: escape all variables, ignore all else. Non-valid code is filtered out by a regex above. |
|
1654 $in_var_now = true; |
|
1655 $in_var_last = false; |
|
1656 $current_var = ''; |
|
1657 $current_var_start_pos = 0; |
|
1658 $current_var_end_pos = 0; |
|
1659 $j = -1; |
|
1660 $condition = $condition . ' '; |
|
1661 $d = strlen($condition); |
|
1662 while($j < $d) |
|
1663 { |
|
1664 $j++; |
|
1665 $in_var_last = $in_var_now; |
|
1666 |
|
1667 $char = substr($condition, $j, 1); |
|
1668 $in_var_now = ( preg_match('#^([A-z0-9_]*){1}$#', $char) ) ? true : false; |
|
1669 if(!$in_var_last && $in_var_now) |
|
1670 { |
|
1671 $current_var_start_pos = $j; |
|
1672 } |
|
1673 if($in_var_last && !$in_var_now) |
|
1674 { |
|
1675 $current_var_end_pos = $j; |
|
1676 } |
|
1677 if($in_var_now) |
|
1678 { |
|
1679 $current_var .= $char; |
|
1680 continue; |
|
1681 } |
|
1682 // OK we are not inside of a variable. That means that we JUST hit the end because the counter ($j) will be advanced to the beginning of the next variable once processing here is complete. |
|
1683 if($char != ' ' && $char != '(' && $char != ')' && $char != 'A' && $char != 'N' && $char != 'D' && $char != 'O' && $char != 'R' && $char != '&' && $char != '|' && $char != '!' && $char != '<' && $char != '>' && $char != '0' && $char != '1' && $char != '2' && $char != '3' && $char != '4' && $char != '5' && $char != '6' && $char != '7' && $char != '8' && $char != '9') |
|
1684 { |
|
1685 // XSS attack! Bail out |
|
1686 $errmsg = '<p><b>Error:</b> Syntax error (possibly XSS attack) caught in template code:</p>'; |
|
1687 $errmsg .= '<pre>'; |
|
1688 $errmsg .= '{if '.htmlspecialchars($condition).'}'; |
|
1689 $errmsg .= "\n "; |
|
1690 for ( $k = 0; $k < $j; $k++ ) |
|
1691 { |
|
1692 $errmsg .= " "; |
|
1693 } |
|
1694 // Show position of error |
|
1695 $errmsg .= '<span style="color: red;">^</span>'; |
|
1696 $errmsg .= '</pre>'; |
|
1697 $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $errmsg, $message); |
|
1698 continue 2; |
|
1699 } |
|
1700 if($current_var != '') |
|
1701 { |
|
1702 $cd = '( isset($this->tpl_bool[\''.$current_var.'\']) && $this->tpl_bool[\''.$current_var.'\'] )'; |
|
1703 $cvt = substr($condition, 0, $current_var_start_pos) . $cd . substr($condition, $current_var_end_pos, strlen($condition)); |
|
1704 $j = $j + strlen($cd) - strlen($current_var); |
|
1705 $current_var = ''; |
|
1706 $condition = $cvt; |
|
1707 $d = strlen($condition); |
|
1708 } |
|
1709 } |
|
1710 $condition = substr($condition, 0, strlen($condition)-1); |
|
1711 $condition = '$chk = ( '.$condition.' ) ? true : false;'; |
|
1712 eval($condition); |
|
1713 |
|
1714 if($chk) |
|
1715 { |
|
1716 if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], 0, strpos($links[2][$i], '{else}')); |
|
1717 else $c = $links[2][$i]; |
|
1718 $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message); |
|
1719 } |
|
1720 else |
|
1721 { |
|
1722 if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], strpos($links[2][$i], '{else}')+6, strlen($links[2][$i])); |
|
1723 else $c = ''; |
|
1724 $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message); |
|
1725 } |
|
1726 } |
|
1727 |
|
1728 preg_match_all('#\{!if ([A-Za-z_-]*)\}(.*?)\{\/if\}#is', $message, $links); |
|
1729 |
|
1730 for($i=0;$i<sizeof($links[1]);$i++) |
|
1731 { |
|
1732 $message = str_replace('{!if '.$links[1][$i].'}'.$links[2][$i].'{/if}', '{CONDITIONAL:'.$i.':'.$random_id.'}', $message); |
|
1733 if(isset($this->tpl_bool[$links[1][$i]]) && $this->tpl_bool[$links[1][$i]]) { |
|
1734 if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], strpos($links[2][$i], '{else}')+6, strlen($links[2][$i])); |
|
1735 else $c = ''; |
|
1736 $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message); |
|
1737 } else { |
|
1738 if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], 0, strpos($links[2][$i], '{else}')); |
|
1739 else $c = $links[2][$i]; |
|
1740 $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message); |
|
1741 } |
|
1742 } |
|
1743 |
|
1744 preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $message, $matches); |
|
1745 foreach ( $matches[1] as $i => $string_id ) |
|
1746 { |
|
1747 $string = $lang->get($string_id); |
|
1748 $string = str_replace('\\', '\\\\', $string); |
|
1749 $string = str_replace('\'', '\\\'', $string); |
|
1750 $message = str_replace_once($matches[0][$i], $string, $message); |
|
1751 } |
|
1752 |
1672 |
1753 /* |
1673 /* |
1754 * HTML RENDERER |
1674 * HTML RENDERER |
1755 */ |
1675 */ |
1756 |
1676 |
1757 // Images |
1677 // Images |
1758 $j = preg_match_all('#\[\[:'.$paths->nslist['File'].'([\w\s0-9_\(\)!@%\^\+\|\.-]+?)\]\]#is', $message, $matchlist); |
1678 $message = RenderMan::process_image_tags($message, $taglist); |
1759 $matches = Array(); |
1679 $message = RenderMan::process_imgtags_stage2($message, $taglist); |
1760 $matches['images'] = $matchlist[1]; |
|
1761 for($i=0;$i<sizeof($matchlist[1]);$i++) |
|
1762 { |
|
1763 if(isPage($paths->nslist['File'].$matches['images'][$i])) |
|
1764 { |
|
1765 $message = str_replace('[[:'.$paths->nslist['File'].$matches['images'][$i].']]', |
|
1766 '<img alt="'.$matches['images'][$i].'" style="border: 0" src="'.makeUrlNS('Special', 'DownloadFile/'.$matches['images'][$i]).'" />', |
|
1767 $message); |
|
1768 } |
|
1769 } |
|
1770 |
1680 |
1771 // Internal links |
1681 // Internal links |
1772 |
1682 $message = RenderMan::parse_internal_links($message, $tplvars['sidebar_button']); |
|
1683 |
|
1684 // External links |
|
1685 |
|
1686 $url_regexp = <<<EOF |
|
1687 ( |
|
1688 (?:https?|ftp|irc):\/\/ # protocol |
|
1689 (?:[^@\s\]"\':]+@)? # username (FTP only but whatever) |
|
1690 (?:(?:(?:[a-z0-9-]+\.)*)[a-z0-9-]+) # hostname |
|
1691 (?:\/[A-z0-9_%\|~`!\!@#\$\^&?=\*\(\):;\.,\/-]*)? # path |
|
1692 ) |
|
1693 EOF; |
|
1694 |
1773 $text_parser = $this->makeParserText($tplvars['sidebar_button']); |
1695 $text_parser = $this->makeParserText($tplvars['sidebar_button']); |
1774 |
1696 |
1775 preg_match_all("#\[\[([^\|\]\n\a\r\t]*?)\]\]#is", $message, $il); |
1697 preg_match_all('/\[' . $url_regexp . '[ ]([^\]]+)\]/isx', $message, $ext_link); |
1776 for($i=0;$i<sizeof($il[1]);$i++) |
|
1777 { |
|
1778 $href = makeUrl(str_replace(' ', '_', $il[1][$i]), null, true); |
|
1779 $text_parser->assign_vars(Array( |
|
1780 'HREF' => $href, |
|
1781 'FLAGS' => '', |
|
1782 'TEXT' => $il[1][$i] |
|
1783 )); |
|
1784 $message = str_replace("[[{$il[1][$i]}]]", $text_parser->run(), $message); |
|
1785 } |
|
1786 |
|
1787 preg_match_all('#\[\[([^\|\]\n\a\r\t]*?)\|([^\]\r\n\a\t]*?)\]\]#is', $message, $il); |
|
1788 for($i=0;$i<sizeof($il[1]);$i++) |
|
1789 { |
|
1790 $href = makeUrl(str_replace(' ', '_', $il[1][$i]), null, true); |
|
1791 $text_parser->assign_vars(Array( |
|
1792 'HREF' => $href, |
|
1793 'FLAGS' => '', |
|
1794 'TEXT' => $il[2][$i] |
|
1795 )); |
|
1796 $message = str_replace("[[{$il[1][$i]}|{$il[2][$i]}]]", $text_parser->run(), $message); |
|
1797 } |
|
1798 |
|
1799 // External links |
|
1800 // $message = preg_replace('#\[(http|ftp|irc):\/\/([a-z0-9\/:_\.\?&%\#@_\\\\-]+?) ([^\]]+)\\]#', '<a href="\\1://\\2">\\3</a><br style="display: none;" />', $message); |
|
1801 // $message = preg_replace('#\[(http|ftp|irc):\/\/([a-z0-9\/:_\.\?&%\#@_\\\\-]+?)\\]#', '<a href="\\1://\\2">\\1://\\2</a><br style="display: none;" />', $message); |
|
1802 |
|
1803 preg_match_all('/\[((https?|ftp|irc):\/\/([^@\s\]"\':]+)?((([a-z0-9-]+\.)*)[a-z0-9-]+)(\/[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]*(\?(([a-z0-9_-]+)(=[A-z0-9_%\|~`\!@#\$\^&\*\(\):;\.,\/-\[\]]+)?((&([a-z0-9_-]+)(=[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]+)?)*))?)?)?) ([^\]]+)\]/is', $message, $ext_link); |
|
1804 |
|
1805 // die('<pre>' . htmlspecialchars( print_r($ext_link, true) ) . '</pre>'); |
|
1806 |
1698 |
1807 for ( $i = 0; $i < count($ext_link[0]); $i++ ) |
1699 for ( $i = 0; $i < count($ext_link[0]); $i++ ) |
1808 { |
1700 { |
1809 $text_parser->assign_vars(Array( |
1701 $text_parser->assign_vars(Array( |
1810 'HREF' => $ext_link[1][$i], |
1702 'HREF' => $ext_link[1][$i], |
1811 'FLAGS' => '', |
1703 'FLAGS' => '', |
1812 'TEXT' => $ext_link[16][$i] |
1704 'TEXT' => $ext_link[2][$i] |
1813 )); |
1705 )); |
1814 $message = str_replace($ext_link[0][$i], $text_parser->run(), $message); |
1706 $message = str_replace($ext_link[0][$i], $text_parser->run(), $message); |
1815 } |
1707 } |
1816 |
1708 |
1817 preg_match_all('/\[((https?|ftp|irc):\/\/([^@\s\]"\':]+)?((([a-z0-9-]+\.)*)[a-z0-9-]+)(\/[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]*(\?(([a-z0-9_-]+)(=[A-z0-9_%\|~`\!@#\$\^&\*\(\):;\.,\/-\[\]]+)?((&([a-z0-9_-]+)(=[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]+)?)*))?)?)?)\]/is', $message, $ext_link); |
1709 preg_match_all('/\[' . $url_regexp . '\]/is', $message, $ext_link); |
1818 |
1710 |
1819 for ( $i = 0; $i < count($ext_link[0]); $i++ ) |
1711 for ( $i = 0; $i < count($ext_link[0]); $i++ ) |
1820 { |
1712 { |
1821 $text_parser->assign_vars(Array( |
1713 $text_parser->assign_vars(Array( |
1822 'HREF' => $ext_link[1][$i], |
1714 'HREF' => $ext_link[1][$i], |
1824 'TEXT' => htmlspecialchars($ext_link[1][$i]) |
1716 'TEXT' => htmlspecialchars($ext_link[1][$i]) |
1825 )); |
1717 )); |
1826 $message = str_replace($ext_link[0][$i], $text_parser->run(), $message); |
1718 $message = str_replace($ext_link[0][$i], $text_parser->run(), $message); |
1827 } |
1719 } |
1828 |
1720 |
1829 $parser1 = $this->makeParserText($tplvars['sidebar_section']); |
1721 $TIME = microtime_float() - $START; |
1830 $parser2 = $this->makeParserText($tplvars['sidebar_section_raw']); |
|
1831 |
|
1832 preg_match_all('#\{slider(2|)=([^\}]*?)\}(.*?)\{\/slider(2|)\}#is', $message, $sb); |
|
1833 |
|
1834 // Modified to support the sweet new template var system |
|
1835 for($i=0;$i<sizeof($sb[1]);$i++) |
|
1836 { |
|
1837 $p = ($sb[1][$i] == '2') ? $parser2 : $parser1; |
|
1838 $p->assign_vars(Array('TITLE'=>$sb[2][$i],'CONTENT'=>$sb[3][$i])); |
|
1839 $message = str_replace("{slider{$sb[1][$i]}={$sb[2][$i]}}{$sb[3][$i]}{/slider{$sb[4][$i]}}", $p->run(), $message); |
|
1840 } |
|
1841 |
1722 |
1842 /* |
1723 /* |
1843 Extras ;-) |
1724 if ( $TIME > 0.02 ) |
1844 $message = preg_replace('##is', '', $message); |
1725 { |
1845 $message = preg_replace('##is', '', $message); |
1726 echo 'template: tplWikiFormat took a while for this one. string dump:<pre>'; |
1846 $message = preg_replace('##is', '', $message); |
1727 echo htmlspecialchars($message); |
1847 $message = preg_replace('##is', '', $message); |
1728 echo '</pre>'; |
1848 $message = preg_replace('##is', '', $message); |
1729 } |
1849 */ |
1730 */ |
1850 |
1731 |
1851 //die('<pre>'.htmlspecialchars($message).'</pre>'); |
|
1852 //eval($message); exit; |
|
1853 return $message; |
1732 return $message; |
|
1733 } |
|
1734 |
|
1735 /** |
|
1736 * Parses conditional {if} blocks in sidebars and other tplWikiFormatted things |
|
1737 * @param string A string potentially containing conditional blocks |
|
1738 * @return string Processed string |
|
1739 */ |
|
1740 |
|
1741 function twf_parse_conditionals($message) |
|
1742 { |
|
1743 if ( !preg_match_all('/\{(!?)if ([a-z0-9_\(\)\|&! ]+)\}(.*?)(?:\{else\}(.*?))?\{\/if\}/is', $message, $matches) ) |
|
1744 { |
|
1745 return $message; |
|
1746 } |
|
1747 foreach ( $matches[0] as $match_id => $full_block ) |
|
1748 { |
|
1749 // 1 = "not" flag |
|
1750 // 2 = condition |
|
1751 // 3 = if true |
|
1752 // 4 = else |
|
1753 $condresult = $this->process_condition($matches[2][$match_id]); |
|
1754 if ( !empty($matches[1][$match_id]) ) |
|
1755 { |
|
1756 if ( $condresult == 1 ) |
|
1757 $condresult = 2; |
|
1758 else if ( $condresult == 2 ) |
|
1759 $condresult = 1; |
|
1760 } |
|
1761 switch($condresult) |
|
1762 { |
|
1763 case 1: |
|
1764 // evaluated to false |
|
1765 $message = str_replace_once($full_block, $matches[4][$match_id], $message); |
|
1766 break; |
|
1767 case 2: |
|
1768 // evaluated to true |
|
1769 $message = str_replace_once($full_block, $matches[3][$match_id], $message); |
|
1770 break; |
|
1771 case 3: |
|
1772 $message = str_replace_once($full_block, "Syntax error: mismatched parentheses (" . htmlspecialchars($matches[2][$match_id]) . ")<br />\n", $message); |
|
1773 break; |
|
1774 case 4: |
|
1775 $message = str_replace_once($full_block, "Syntax error: illegal character (" . htmlspecialchars($matches[2][$match_id]) . ")<br />\n", $message); |
|
1776 break; |
|
1777 case 5: |
|
1778 $message = str_replace_once($full_block, "Syntax error: illegal sequence (" . htmlspecialchars($matches[2][$match_id]) . ")<br />\n", $message); |
|
1779 break; |
|
1780 } |
|
1781 } |
|
1782 return $message; |
|
1783 } |
|
1784 |
|
1785 /** |
|
1786 * Inner-loop parser for a conditional block. Verifies a string condition to make sure it's syntactically correct, then returns what it evaluates to. |
|
1787 * Return values: |
|
1788 * 1 - string evaluates to true |
|
1789 * 2 - string evaluates to false |
|
1790 * 3 - Syntax error - mismatched parentheses |
|
1791 * 4 - Syntax error - unknown token |
|
1792 * 5 - Syntax error - invalid sequence |
|
1793 * @param string |
|
1794 * @return int |
|
1795 * |
|
1796 */ |
|
1797 |
|
1798 function process_condition($condition) |
|
1799 { |
|
1800 // make sure parentheses are matched |
|
1801 $parentheses = preg_replace('/[^\(\)]/', '', $condition); |
|
1802 if ( !empty($parentheses) ) |
|
1803 { |
|
1804 $i = 0; |
|
1805 $parentheses = enano_str_split($parentheses); |
|
1806 foreach ( $parentheses as $chr ) |
|
1807 { |
|
1808 $inc = ( $chr == '(' ) ? 1 : -1; |
|
1809 $i += $inc; |
|
1810 } |
|
1811 if ( $i != 0 ) |
|
1812 { |
|
1813 // mismatched parentheses |
|
1814 return 3; |
|
1815 } |
|
1816 } |
|
1817 // sequencer check |
|
1818 // first, pad all sequences of characters with spaces |
|
1819 $seqcheck = preg_replace('/([a-z0-9_]+)/i', '\\1 ', $condition); |
|
1820 $seqcheck = preg_replace('/([&|()!])/i', '\\1 ', $seqcheck); |
|
1821 // now shrink all spaces to one space each |
|
1822 $seqcheck = preg_replace('/[ ]+/', ' ', $seqcheck); |
|
1823 |
|
1824 // explode it. the allowed sequences are: |
|
1825 // - TOKEN_NOT + TOKEN_VARIABLE |
|
1826 // - TOKEN_NOT + TOKEN_PARENTHLEFT |
|
1827 // - TOKEN_BOOLOP + TOKEN_NOT |
|
1828 // - TOKEN_PARENTHRIGHT + TOKEN_NOT |
|
1829 // - TOKEN_VARIABLE + TOKEN_BOOLOP |
|
1830 // - TOKEN_BOOLOP + TOKEN_PARENTHLEFT |
|
1831 // - TOKEN_PARENTHLEFT + TOKEN_VARIABLE |
|
1832 // - TOKEN_BOOLOP + TOKEN_VARIABLE |
|
1833 // - TOKEN_VARIABLE + TOKEN_PARENTHRIGHT |
|
1834 // - TOKEN_PARENTHRIGHT + TOKEN_BOOLOP |
|
1835 $seqcheck = explode(' ', trim($seqcheck)); |
|
1836 $last_item = TOKEN_BOOLOP; |
|
1837 foreach ( $seqcheck as $i => $token ) |
|
1838 { |
|
1839 // determine type |
|
1840 if ( $token == '(' ) |
|
1841 { |
|
1842 $type = TOKEN_PARENTHLEFT; |
|
1843 } |
|
1844 else if ( $token == ')' ) |
|
1845 { |
|
1846 $type = TOKEN_PARENTHRIGHT; |
|
1847 } |
|
1848 else if ( $token == '!' ) |
|
1849 { |
|
1850 $type = TOKEN_NOT; |
|
1851 } |
|
1852 else if ( strtolower($token) == 'and' || strtolower($token) == 'or' || $token == '&&' || $token == '||' ) |
|
1853 { |
|
1854 $type = TOKEN_BOOLOP; |
|
1855 } |
|
1856 else if ( preg_match('/^[a-z0-9_]+$/i', $token) ) |
|
1857 { |
|
1858 $type = TOKEN_VARIABLE; |
|
1859 // at this point it's considered safe to wrap it |
|
1860 $seqcheck[$i] = "( isset(\$this->tpl_bool['$token']) && \$this->tpl_bool['$token'] )"; |
|
1861 } |
|
1862 else |
|
1863 { |
|
1864 // syntax error - doesn't match known token types |
|
1865 return 4; |
|
1866 } |
|
1867 // inner sequence check |
|
1868 if ( |
|
1869 ( $last_item == TOKEN_BOOLOP && $type == TOKEN_NOT ) || |
|
1870 ( $last_item == TOKEN_PARENTHRIGHT && $type == TOKEN_NOT ) || |
|
1871 ( $last_item == TOKEN_NOT && $type == TOKEN_VARIABLE ) || |
|
1872 ( $last_item == TOKEN_NOT && $type == TOKEN_PARENTHLEFT ) || |
|
1873 ( $last_item == TOKEN_VARIABLE && $type == TOKEN_BOOLOP ) || |
|
1874 ( $last_item == TOKEN_BOOLOP && $type == TOKEN_PARENTHLEFT ) || |
|
1875 ( $last_item == TOKEN_PARENTHLEFT && $type == TOKEN_VARIABLE ) || |
|
1876 ( $last_item == TOKEN_BOOLOP && $type == TOKEN_VARIABLE ) || |
|
1877 ( $last_item == TOKEN_VARIABLE && $type == TOKEN_PARENTHRIGHT ) || |
|
1878 ( $last_item == TOKEN_PARENTHRIGHT && $type == TOKEN_BOOLOP ) |
|
1879 ) |
|
1880 { |
|
1881 // sequence is good, continue |
|
1882 } |
|
1883 else |
|
1884 { |
|
1885 // sequence is invalid, break out |
|
1886 return 5; |
|
1887 } |
|
1888 $last_item = $type; |
|
1889 } |
|
1890 // passed all checks |
|
1891 $seqcheck = implode(' ', $seqcheck); |
|
1892 $result = eval("return ( $seqcheck ) ? true : false;"); |
|
1893 return ( $result ) ? 2 : 1; |
1854 } |
1894 } |
1855 |
1895 |
1856 /** |
1896 /** |
1857 * Print a text field that auto-completes a username entered into it. |
1897 * Print a text field that auto-completes a username entered into it. |
1858 * @param string $name - the name of the form field |
1898 * @param string $name - the name of the form field |
2031 unset($parser); |
2092 unset($parser); |
2032 } |
2093 } |
2033 $db->free_result(); |
2094 $db->free_result(); |
2034 if(isset($vars['sidebar_bottom'])) |
2095 if(isset($vars['sidebar_bottom'])) |
2035 { |
2096 { |
2036 $left .= $this->parse($vars['sidebar_bottom']); |
2097 $bottom = $this->parse($vars['sidebar_bottom']); |
2037 $right .= $this->parse($vars['sidebar_bottom']); |
2098 $left .= $bottom; |
|
2099 $right .= $bottom; |
2038 } |
2100 } |
2039 $min = ''; |
2101 $min = ''; |
2040 if(isset($vars['sidebar_top'])) |
2102 if(isset($vars['sidebar_top'])) |
2041 { |
2103 { |
2042 $min .= $this->parse($vars['sidebar_top']); |
2104 $min .= $top; |
2043 } |
2105 } |
2044 if(isset($vars['sidebar_bottom'])) |
2106 if(isset($vars['sidebar_bottom'])) |
2045 { |
2107 { |
2046 $min .= $this->parse($vars['sidebar_bottom']); |
2108 $min .= $bottom; |
2047 } |
2109 } |
2048 return Array($left, $right, $min); |
2110 $return = Array($left, $right, $min); |
|
2111 if ( $cache_enable ) |
|
2112 { |
|
2113 $cachestore = Language::var_export_string($return); |
|
2114 $cachestore = str_replace($session->username, '$USERNAME$', $cachestore); |
|
2115 $cachestore = <<<EOF |
|
2116 <?php |
|
2117 /** |
|
2118 * Automatically generated cache of the sidebar for guests. |
|
2119 * Do not modify this, it is refreshed every 15 minutes. |
|
2120 */ |
|
2121 |
|
2122 \$sidebar_cache = $cachestore; |
|
2123 EOF; |
|
2124 $fh = @fopen($cache_file, 'w'); |
|
2125 if ( $fh ) |
|
2126 { |
|
2127 fwrite($fh, $cachestore); |
|
2128 fclose($fh); |
|
2129 } |
|
2130 setConfig('sidebar_anon_cache_time', time()); |
|
2131 } |
|
2132 return $return; |
2049 } |
2133 } |
2050 |
2134 |
2051 function initLinksWidget() |
2135 function initLinksWidget() |
2052 { |
2136 { |
2053 global $db, $session, $paths, $template, $plugins; // Common objects |
2137 global $db, $session, $paths, $template, $plugins; // Common objects |
2054 // SourceForge/W3C buttons |
2138 // SourceForge/W3C buttons |
2055 $ob = Array(); |
2139 $ob = Array(); |
|
2140 // FIXME: l10n |
2056 $admintitle = ( $session->user_level >= USER_LEVEL_ADMIN ) ? 'title="You may disable this button in the admin panel under General Configuration."' : ''; |
2141 $admintitle = ( $session->user_level >= USER_LEVEL_ADMIN ) ? 'title="You may disable this button in the admin panel under General Configuration."' : ''; |
2057 if(getConfig('sflogo_enabled')=='1') |
2142 if(getConfig('sflogo_enabled')=='1') |
2058 { |
2143 { |
2059 $sflogo_secure = ( isset($_SERVER['HTTPS']) ) ? 'https' : 'http'; |
2144 $sflogo_secure = ( isset($_SERVER['HTTPS']) ) ? 'https' : 'http'; |
2060 $ob[] = '<a style="text-align: center;" href="http://sourceforge.net/" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border-width: 0px;" alt="SourceForge.net Logo" src="' . $sflogo_secure . '://sflogo.sourceforge.net/sflogo.php?group_id='.getConfig('sflogo_groupid').'&type='.getConfig('sflogo_type').'" /></a>'; |
2145 $ob[] = '<a style="text-align: center;" href="http://sourceforge.net/" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border-width: 0px;" alt="SourceForge.net Logo" src="' . $sflogo_secure . '://sflogo.sourceforge.net/sflogo.php?group_id='.getConfig('sflogo_groupid').'&type='.getConfig('sflogo_type').'" /></a>'; |