Project

General

Profile

« Previous | Next » 

Revision 1520

Added by darkviper about 13 years ago

/modules/output_filter completely recoded
+ new filter for relative-URL added
+ some small fixes
/admin/admintools/tool.php completely recoded
/wb/index.php output_filter request changed to adopt new output_filter

View differences:

branches/2.8.x/CHANGELOG
12 12

  
13 13
=============================== FEATURES FREEZE ================================
14 14
----------------------------------- Fixes 2.8.2 --------------------------------
15
09 Nov-2011 Build 1519 Werner v.d.Decken(DarkViper)
16
! /modules/output_filter completely recoded
17
+ new filter for relative-URL added
18
+ some small fixes
19
! /admin/admintools/tool.php completely recoded
20
! /wb/index.php output_filter request changed to adopt new output_filter
15 21
26 Okt-2011 Build 1518 Dietmar Woellbrink (Luisehahne)
16 22
# see http://www.websitebaker2.org/forum/index.php/topic,22649.msg152666.html#msg152666
17 23
24 Okt-2011 Build 1517 Dietmar Woellbrink (Luisehahne)
branches/2.8.x/wb/admin/interface/version.php
52 52

  
53 53
// check if defined to avoid errors during installation (redirect to admin panel fails if PHP error/warnings are enabled)
54 54
if(!defined('VERSION')) define('VERSION', '2.8.2');
55
if(!defined('REVISION')) define('REVISION', '1518');
55
if(!defined('REVISION')) define('REVISION', '1519');
branches/2.8.x/wb/admin/admintools/tool.php
3 3
 *
4 4
 * @category        admin
5 5
 * @package         admintools
6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
8
 * @copyright       2009-2011, Website Baker Org. e.V.
6
 * @author          WB-Project, Werner v.d. Decken
7
 * @copyright       2011, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11
 * @platform        WebsiteBaker 2.8.x
10
 * @platform        WebsiteBaker 2.8.2
12 11
 * @requirements    PHP 5.2.2 and higher
13 12
 * @version         $Id$
14 13
 * @filesource		$HeadURL$
15 14
 * @lastmodified    $Date$
16 15
 *
17 16
 */
18

  
19 17
require('../../config.php');
20 18
require_once(WB_PATH.'/framework/class.admin.php');
21 19
require_once(WB_PATH.'/framework/functions.php');
22 20

  
23
if(!isset($_GET['tool'])) {
24
	header("Location: index.php");
25
	exit(0);
26
} else {
27
	$array = array();
28
	preg_match("/[a-z,_,a-z]+/i",$_GET['tool'],$array);
29
	$tool = $array[0];
30
}
31

  
32
$ModulesUsingFTAN = '';
33
$admin_header =  true;
34
if(isset($_POST['save_settings'])) {
35
	$ModulesUsingFTAN = WB_PATH.'/modules/'.$tool.'/FTAN_SUPPORTED';
36
}
37

  
38
$admin_header = (file_exists($ModulesUsingFTAN) && is_file($ModulesUsingFTAN)) == false;
39
$admin = new admin('admintools', 'admintools', $admin_header );
40

  
41
// Check if tool is installed
42
$result = $database->query("SELECT * FROM ".TABLE_PREFIX."addons WHERE type = 'module' AND function = 'tool' AND directory = '".preg_replace('/[^a-z0-9_-]/i', "", $tool)."'");
43
if($result->numRows() == 0) {
44
	header("Location: index.php");
45
	exit(0);
46
}
47
$tools = $result->fetchRow();
48
if(!isset($_POST['save_settings'])) {
49

  
50
?>
51
<h4>
52
	<a href="<?php echo ADMIN_URL; ?>/admintools/index.php"><?php echo $HEADING['ADMINISTRATION_TOOLS']; ?></a>
53
	&raquo;
54
	<?php echo $tools['name']; ?>
55
</h4>
56
<?php
57
}
58
require(WB_PATH.'/modules/'.$tools['directory'].'/tool.php');
59

  
60
$admin->print_footer();
21
	$toolDir = (isset($_GET['tool']) && (trim($_GET['tool']) != '') ? trim($_GET['tool']) : '');
22
	$doSave = (isset($_POST['save_settings']) || (isset($_POST['action']) && strtolower($_POST['action']) == 'save'));
23
// test for valid tool name
24
	if(preg_match('/^[a-z][a-z_\-0-9]{2,}$/i', $toolDir)) {
25
	// Check if tool is installed
26
		$sql = 'SELECT `name` FROM `'.TABLE_PREFIX.'addons` '.
27
		       'WHERE `type`=\'module\' AND `function`=\'tool\' '.
28
		              'AND `directory`=\''.$toolDir.'\'';
29
		if(($toolName = $database->get_one($sql))) {
30
		// create admin-object and print header if FTAN is NOT supported AND function 'save' is requested
31
			$admin_header = !(is_file(WB_PATH.'/modules/'.$toolDir.'/FTAN_SUPPORTED') && $doSave);
32
			$admin = new admin('admintools', 'admintools', $admin_header );
33
			if(!$doSave) {
34
			// show title if not function 'save' is requested
35
				print '<h4><a href="'.ADMIN_URL.'/admintools/index.php" '.
36
				      'title="'.$HEADING['ADMINISTRATION_TOOLS'].'">'.
37
				      $HEADING['ADMINISTRATION_TOOLS'].'</a>'.
38
					  '&raquo'.$toolName.'</h4>'."\n";
39
			}
40
			// include modules tool.php
41
			require(WB_PATH.'/modules/'.$toolDir.'/tool.php');
42
			$admin->print_footer();
43
		}else {
44
		// no installed module found, jump to index.php of admintools
45
			header('location: '.ADMIN_URL.'/admintools/index.php');
46
			exit(0);
47
		}
48
	}else {
49
	// invalid module name requested, jump to index.php of admintools
50
		header('location: '.ADMIN_URL.'/admintools/index.php');
51
		exit(0);
52
	}
branches/2.8.x/wb/admin/admintools/index.php
3 3
 *
4 4
 * @category        admin
5 5
 * @package         admintools
6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
8
 * @copyright       2009-2011, Website Baker Org. e.V.
6
 * @author          WB-Project, Werner v.d. Decken
7
 * @copyright       2011, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11 10
 * @platform        WebsiteBaker 2.8.x
branches/2.8.x/wb/index.php
4 4
 * @category        frontend
5 5
 * @package         page
6 6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
8
 * @copyright       2009-2011, Website Baker Org. e.V.
7
 * @copyright       2009-, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11 10
 * @platform        WebsiteBaker 2.8.x
......
130 129
   $wb->preprocess($output);
131 130
}
132 131
// Load Droplet engine and process
133
if(file_exists(WB_PATH .'/modules/droplets/droplets.php'))
134
{
135
    include_once(WB_PATH .'/modules/droplets/droplets.php');
136
    if(function_exists('evalDroplets'))
137
    {
138
		$output = evalDroplets($output);
139
    }
140
}
132
	if(file_exists(WB_PATH .'/modules/droplets/droplets.php')) {
133
		include_once(WB_PATH .'/modules/droplets/droplets.php');
134
		if(function_exists('evalDroplets')) {
135
			$output = evalDroplets($output);
136
		}
137
	}
141 138
// Load backwards compatible frontend filter support and process
142
if(file_exists(WB_PATH .'/modules/output_filter/filter-routines.php'))
143
{
144
    include_once(WB_PATH .'/modules/output_filter/filter-routines.php');
145
    if(function_exists('filter_frontend_output'))
146
    {
147
        $output = filter_frontend_output($output);
148
    }
149
}
139
	if(file_exists(WB_PATH .'/modules/output_filter/filter-routines.php')) {
140
		include_once(WB_PATH .'/modules/output_filter/filter-routines.php');
141
		if(function_exists('executeFrontendOutputFilter')) {
142
			$output = executeFrontendOutputFilter($output);
143
		}elseif(function_exists('filter_frontend_output')) {
144
			$output = filter_frontend_output($output);
145
		}
146

  
147
	}
150 148
// move css definitions into head section
151
if(function_exists('moveCssToHead')) {
152
	$output = moveCssToHead($output);
153
}
149
	if(function_exists('moveCssToHead')) {
150
		$output = moveCssToHead($output);
151
	}
154 152
// now send complete page to the browser
155 153
echo $output;
156 154
// end of wb-script
branches/2.8.x/wb/modules/output_filter/uninstall.php
3 3
 *
4 4
 * @category        modules
5 5
 * @package         output_filter
6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
8
 * @copyright       2009-2011, Website Baker Org. e.V.
6
 * @author          Christian Sommer, WB-Project, Werner v.d. Decken
7
 * @copyright       2009-, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11
 * @platform        WebsiteBaker 2.8.x
10
 * @platform        WebsiteBaker 2.8.2
12 11
 * @requirements    PHP 5.2.2 and higher
13 12
 * @version         $Id$
14 13
 * @filesource		$HeadURL$
15 14
 * @lastmodified    $Date$
16 15
 *
17 16
 */
17
/* -------------------------------------------------------- */
18
// Must include code to stop this file being accessed directly
19
require_once( dirname(dirname(dirname(__FILE__))).'/framework/globalExceptionHandler.php');
20
if(!defined('WB_PATH')) { throw new IllegalFileException(); }
21
/* -------------------------------------------------------- */
18 22

  
19
// Must include code to stop this file being access directly
20
if(defined('WB_PATH') == false) { die("Cannot access this file directly"); }
21

  
22 23
$table = TABLE_PREFIX .'mod_output_filter';
23 24
$database->query("DROP TABLE IF EXISTS `$table`");
branches/2.8.x/wb/modules/output_filter/filter-routines.php
3 3
 *
4 4
 * @category        modules
5 5
 * @package         output_filter
6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
8
 * @copyright       2009-2011, Website Baker Org. e.V.
6
 * @author          Christian Sommer, WB-Project, Werner v.d. Decken
7
 * @copyright       2011, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11
 * @platform        WebsiteBaker 2.8.x
10
 * @platform        WebsiteBaker 2.8.2
12 11
 * @requirements    PHP 5.2.2 and higher
13 12
 * @version         $Id$
14 13
 * @filesource		$HeadURL$
15 14
 * @lastmodified    $Date$
16 15
 *
17 16
 */
17
/* -------------------------------------------------------- */
18
// Must include code to stop this file being accessed directly
19
require_once( dirname(dirname(dirname(__FILE__))).'/framework/globalExceptionHandler.php');
20
if(!defined('WB_PATH')) { throw new IllegalFileException(); }
21
/* -------------------------------------------------------- */
18 22

  
19
// Must include code to stop this file being access directly
20
if(defined('WB_PATH') == false) { die("Cannot access this file directly"); }
21

  
22
// function to read the current filter settings
23
if (!function_exists('get_output_filter_settings')) {
24
	function get_output_filter_settings() {
23
/* ************************************************************************** */
24
/**
25
 * execute the frontend output filter to modify email addresses
26
 * @param string actual content
27
 * @return string modified content
28
 */
29
	function executeFrontendOutputFilter($content) {
30
		// get output filter settings from database
31
		$filter_settings = getOutputFilterSettings();
32
		$output_filter_mode = 0;
33
		$output_filter_mode |= ($filter_settings['email_filter'] * pow(2, 0));  // n | 2^0
34
		$output_filter_mode |= ($filter_settings['mailto_filter'] * pow(2, 1)); // n | 2^1
35
		define('OUTPUT_FILTER_AT_REPLACEMENT', $filter_settings['at_replacement']);
36
		define('OUTPUT_FILTER_DOT_REPLACEMENT', $filter_settings['dot_replacement']);
37
/* ### filter type: full qualified URLs ##################################### */
38
        if($filter_settings['sys_rel'] == 1){
39
			$content = _doFilterRelUrl($content);
40
		}
41
/* ### filter type: protect email addresses ################################# */
42
		if( ($output_filter_mode & pow(2, 0)) || ($output_filter_mode & pow(2, 1)) ) {
43
			$content = _doFilterEmail($content, $output_filter_mode);
44
		}
45
/* ### end of filters ####################################################### */
46
		return $content;
47
	}
48
/* ************************************************************************** */
49
/**
50
 * function to read the current filter settings
51
 * @global object $database
52
 * @global object $admin
53
 * @param void
54
 * @return array contains all settings
55
 */
56
	function getOutputFilterSettings() {
25 57
		global $database, $admin;
26
	// be sure field is in table (suppresses strict warning)
27
		$table_name = TABLE_PREFIX .'mod_output_filter';
28
		$field_name = 'sys_rel';
29
		$description = 'VARCHAR(1) NOT NULL DEFAULT \'0\'';
30
		$msg_flag = ($database->field_add($table_name,$field_name,$description ));
31
		// connect to database and read out filter settings
32
		$result = $database->query("SELECT * FROM " .TABLE_PREFIX ."mod_output_filter");
33
		if($result && $result->numRows() > 0) {
34
			// get all data
35
			$data = $result->fetchRow();
36
			$filter_settings['sys_rel'] = $admin->strip_slashes($data['sys_rel']);
37
			$filter_settings['email_filter'] = $admin->strip_slashes($data['email_filter']);
38
			$filter_settings['mailto_filter'] = $admin->strip_slashes($data['mailto_filter']);
39
			$filter_settings['at_replacement'] = $admin->strip_slashes($data['at_replacement']);
40
			$filter_settings['dot_replacement'] = $admin->strip_slashes($data['dot_replacement']);
41
		} else {
42
			// something went wrong, use default values
43
			$filter_settings['sys_rel'] = '0';
44
			$filter_settings['email_filter'] = '0';
45
			$filter_settings['mailto_filter'] = '0';
46
			$filter_settings['at_replacement'] = '(at)';
47
			$filter_settings['dot_replacement'] = '(dot)';
58
	// set default values
59
		$settings = array(
60
			'sys_rel'         => 0,
61
			'email_filter'    => 0,
62
			'mailto_filter'   => 0,
63
			'at_replacement'  => '(at)',
64
			'dot_replacement' => '(dot)'
65
		);
66
	// be sure field 'sys_rel' is in table
67
		$database->field_add( TABLE_PREFIX.'mod_output_filter', 'sys_rel', 'INT NOT NULL DEFAULT \'0\' FIRST');
68
	// request settings from database
69
		$sql = 'SELECT * FROM `'.TABLE_PREFIX.'mod_output_filter';
70
		if(($res = $database->query($sql))) {
71
			if(($rec = $res->fetchRow())) {
72
				$settings = $rec;
73
				$settings['at_replacement']  = $admin->strip_slashes($settings['at_replacement']);
74
				$settings['dot_replacement'] = $admin->strip_slashes($settings['dot_replacement']);
75
			}
48 76
		}
49
		
50
		// return array with filter settings
51
		return $filter_settings;
77
	// return array with filter settings
78
		return $settings;
52 79
	}
53
}
54

  
55
// function to filter the output before displaying it on the frontend
56
if (!function_exists('filter_frontend_output')) {
57
	function filter_frontend_output($content) {
58
		// get output filter settings from database
59
		$filter_settings = get_output_filter_settings();
60
		$location = '';
61
		if($filter_settings['sys_rel'] == '1'){
62
			if( !isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) == 'off' ) {
63
				define('SYS_HTTPS', false);
64
				define('SYS_PORT', (($_SERVER['SERVER_PORT'] != '80') ? ':'.$_SERVER['SERVER_PORT'] : '') );
65
				define('SYS_PROTOCOL', 'http');
66
			} else {
67
				define('SYS_HTTPS', true);
68
				define('SYS_PORT', (($_SERVER['SERVER_PORT'] != '443') ? ':'.$_SERVER['SERVER_PORT'] : '') );
69
				define('SYS_PROTOCOL', 'https');
80
/* ************************************************************************** */
81
/**
82
 * Convert full qualified, local URLs into relative URLs
83
 * @param string $content
84
 * @return string
85
 */
86
	function _doFilterRelUrl($content) {
87
		$content = preg_replace_callback(
88
				'/((?:href|src)\s*=\s*")([^\"]*?)(")/iU',
89
				create_function('$matches',
90
				    '$retval = $matches[0]; '.
91
		            '$h = parse_url($matches[2], PHP_URL_HOST); '.
92
		            'if(stripos(WB_URL, $h) !== false) { '.
93
		            '$a = parse_url($matches[2]); '.
94
		            '$p = (isset($a[\'path\']) ? $a[\'path\'] : \'\'); '.
95
		            '$q = (isset($a[\'query\']) ? \'?\'.$a[\'query\'] : \'\'); '.
96
		            '$f = (isset($a[\'fragment\']) ? \'#\'.$a[\'fragment\'] : \'\'); '.
97
		            '$p .= ($q.$f); '.
98
		            '$retval = $matches[1]."/".(isset($p) ? ltrim(str_replace("//", "/", $p), "/") : "").$matches[3]; '.
99
		            '} '.
100
		            'return $retval;'),
101
		        $content);
102
		return $content;
103
	}
104
/* ************************************************************************** */
105
/**
106
 * protect email addresses (replace '@' and '.' and obfuscate address
107
 * @param string $content
108
 * @return string
109
 */
110
	function _doFilterEmail($content, $output_filter_mode) {
111
	// test if js-decryption is installed
112
		if( preg_match('/<head.*<.*src=\".*\/mdcr.js.*>.*<\/head/siU', $content) ) {
113
			$output_filter_mode |= pow(2, 2); // n | 2^2
114
		}else {
115
		// try to insert js-decrypt into <head> if available
116
			$script = str_replace('\\', '/', dirname(__FILE__)).'/js/mdcr.js';
117
			if(is_readable($script)) {
118
				$scriptLink = '<script src="'.$script.'" type="text/javascript"></script>';
119
				$regex = '/(.*)(<\s*?\/\s*?head\s*>.*)/isU';
120
				$replace = '$1<script src="'.$scriptLink.'" type="text/javascript"></script>$2';
121
				$content = preg_replace ($regex, $replace, $content);
122
				$output_filter_mode |= pow(2, 2); // n | 2^2
70 123
			}
71
			$tmp = '';
72
			if( isset($_SERVER['HTTP_HOST']) ) {
73
				$tmp = $_SERVER['HTTP_HOST'];
74
			} elseif( isset($_SERVER['SERVER_NAME']) ) {
75
				$tmp = $_SERVER['SERVER_NAME'];
76
			}
77

  
78
			define('WB_HOST', preg_replace('/:[0-9]*$/', '', $tmp));
79
			$location = SYS_PROTOCOL.'://'.WB_HOST.SYS_PORT;
80
			$searchfor = '/(<.*?=\s*?\")(?:'.preg_quote($location, '/').'\/?)(.*?\".*?>)/i';
81
			$content = preg_replace($searchfor, '$1/$2', $content);
82
			$content = preg_replace('/(<.*?(?:href|src)\s*=\s*?\")(\".*?>)/i', '$1/$2', $content);
83

  
84 124
		}
85

  
125
	// define some constants so we do not call the database in the callback functions again
126
		define('OUTPUT_FILTER_MODE', (int)$output_filter_mode);
127
/* *** obfuscate mailto addresses by js:mdcr *** */
86 128
		// work out the defined output filter mode: possible output filter modes: [0], 1, 2, 3, 6, 7
87 129
		// 2^0 * (0.. disable, 1.. enable) filtering of mail addresses in text
88 130
		// 2^1 * (0.. disable, 1.. enable) filtering of mail addresses in mailto links
89 131
		// 2^2 * (0.. disable, 1.. enable) Javascript mailto encryption (only if mailto filtering enabled)
90 132

  
91
		// only filter output if we are supposed to
92
		if($filter_settings['email_filter'] != '1' && $filter_settings['mailto_filter'] != '1'){
93
			// do nothing more
94
			return $content;
95
		}
96

  
97
		// check if non mailto mail addresses needs to be filtered
98
		$output_filter_mode = ($filter_settings['email_filter'] == '1') ? 1 : 0;		// 0|1
99

  
100
		// check if mailto mail addresses needs to be filtered
101
		if($filter_settings['mailto_filter'] == '1') {
102
			$output_filter_mode = $output_filter_mode + 2;								// 0|2
103

  
104
			// check if Javascript mailto encryption is enabled (call register_frontend_functions in the template)
105
           $search_pattern = '/<.*src=\".*\/mdcr.js.*>/iU';
106
           if(preg_match($search_pattern, $content))
107
           {
108
            $output_filter_mode = $output_filter_mode + 4;       // 0|4
109
           }
110
/*
111
			$search = '<script src="' .WB_URL .'/modules/output_filter/js/mdcr.js" type="text/javascript"></script>';
112
			$search_droplet = '<script src="' .WB_URL .'/modules/droplets/js/mdcr.js" type="text/javascript"></script>';
113
			if(strpos($content, $search) !== false || strpos($content, $search_droplet) !== false) {
114
				$output_filter_mode = $output_filter_mode + 4;							// 0|4
115
			}
116
*/
117
		}
118
		
119
		// define some constants so we do not call the database in the callback function again
120
		define('OUTPUT_FILTER_MODE', (int) $output_filter_mode);
121
		define('OUTPUT_FILTER_AT_REPLACEMENT', $filter_settings['at_replacement']);
122
		define('OUTPUT_FILTER_DOT_REPLACEMENT', $filter_settings['dot_replacement']);
123
		
124 133
		// first search part to find all mailto email addresses
125 134
		$pattern = '#(<a[^<]*href\s*?=\s*?"\s*?mailto\s*?:\s*?)([A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4})([^"]*?)"([^>]*>)(.*?)</a>';
126 135
		// second part to find all non mailto email addresses
127 136
		$pattern .= '|(value\s*=\s*"|\')??\b([A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4})\b#i';
128
		/*
129
		Sub 1:\b(<a.[^<]*href\s*?=\s*?"\s*?mailto\s*?:\s*?)			-->	"<a id="yyy" class="xxx" href = " mailto :" ignoring white spaces
130
		Sub 2:([A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4})			-->	the email address in the mailto: part of the mail link
131
		Sub 3:([^"]*?)"												--> possible ?Subject&cc... stuff attached to the mail address
132
		Sub 4:([^>]*>)												--> all class or id statements after the mailto but before closing ..>
133
		Sub 5:(.*?)</a>\b											--> the mailto text; all characters between >xxxxx</a>
134
		Sub 6:|\b([A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4})\b		--> email addresses which may appear in the text (require word boundaries)
135
		*/
136
			
137
/*
138
	Sub 1:\b(<a.[^<]*href\s*?=\s*?"\s*?mailto\s*?:\s*?)			-->	"<a id="yyy" class="xxx" href = " mailto :" ignoring white spaces
139
	Sub 2:([A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4})			-->	the email address in the mailto: part of the mail link
140
	Sub 3:([^"]*?)"												--> possible ?Subject&cc... stuff attached to the mail address
141
	Sub 4:([^>]*>)												--> all class or id statements after the mailto but before closing ..>
142
	Sub 5:(.*?)</a>\b											--> the mailto text; all characters between >xxxxx</a>
143
	Sub 6:|\b([A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4})\b		--> email addresses which may appear in the text (require word boundaries)
144
*/
137 145
		// find all email addresses embedded in the content and filter them using a callback function
138
		$content = preg_replace_callback($pattern, 'filter_mail_addresses', $content);
139
		// href can't be empty
140
		$searchfor = '/(<.*?=\s*?\")(?:'.preg_quote($location, '/').')(.*?\".*?>)/i';
141
		$content = preg_replace($searchfor, '$1$2', $content);
146
		$content = preg_replace_callback($pattern, '_cbDoExecuteFilter', $content);
142 147
		return $content;
143 148
	}
144
}		
145

  
146

  
147
// function to filter mail addresses embedded in text or mailto links before outputing them on the frontend
148
if (!function_exists('filter_mail_addresses')) {
149
	function filter_mail_addresses($match) { 
150
		
151
		// check if required output filter mode is defined
152
		if(!(defined('OUTPUT_FILTER_MODE') && defined('OUTPUT_FILTER_MODE') && defined('OUTPUT_FILTER_MODE'))) {
149
/* ************************************************************************** */
150
/**
151
 * callback-function for function _doFilterEmail() to proceed search results
152
 * @param array results from preg_replace
153
 * @return string proceeded replacement string
154
 */
155
	function _cbDoExecuteFilter($match) {
156
		// check if required arguments are defined
157
		if(!( defined('OUTPUT_FILTER_MODE')
158
		      && defined('OUTPUT_FILTER_AT_REPLACEMENT')
159
		      && defined('OUTPUT_FILTER_MODE')
160
    	    ) ) {
153 161
			return $match[0];
154 162
		}
155
		
156 163
		$search = array('@', '.');
157 164
		$replace = array(OUTPUT_FILTER_AT_REPLACEMENT ,OUTPUT_FILTER_DOT_REPLACEMENT);
158
		
159 165
		// check if the match contains the expected number of subpatterns (6|8)
160
		if(count($match) == 8) {
161
			/**
162
				OUTPUT FILTER FOR EMAIL ADDRESSES EMBEDDED IN TEXT
163
			**/
164
			
166
		switch (count($match)) {
167
			case 8:
168
			/** OUTPUT FILTER FOR EMAIL ADDRESSES EMBEDDED IN TEXT **/
165 169
			// 1.. text mails only, 3.. text mails + mailto (no JS), 7 text mails + mailto (JS)
166
			if(!in_array(OUTPUT_FILTER_MODE, array(1,3,7))) return $match[0];
167

  
168
			// do not filter mail addresses included in input tags (<input ... value = "test@mail)
169
			if (strpos($match[6], 'value') !== false) return $match[0];
170
			
171
			// filtering of non mailto email addresses enabled
172
			return str_replace($search, $replace, $match[0]);
173
				
174
		} elseif(count($match) == 6) {
175
			/**
176
				OUTPUT FILTER FOR EMAIL ADDRESSES EMBEDDED IN MAILTO LINKS
177
			**/
178

  
170
				if(!in_array(OUTPUT_FILTER_MODE, array(1,3,7))) return $match[0];
171
				// do not filter mail addresses included in input tags (<input ... value = "test@mail)
172
				if (strpos($match[6], 'value') !== false) return $match[0];
173
				// filtering of non mailto email addresses enabled
174
				return str_replace($search, $replace, $match[0]);
175
			break;
176
			case 6:
177
			/** OUTPUT FILTER FOR EMAIL ADDRESSES EMBEDDED IN MAILTO LINKS **/
179 178
			// 2.. mailto only (no JS), 3.. text mails + mailto (no JS), 6.. mailto only (JS), 7.. all filters active
180
			if(!in_array(OUTPUT_FILTER_MODE, array(2,3,6,7))) return $match[0];
181
			
182
			// check if last part of the a href link: >xxxx</a> contains a email address we need to filter
183
			$pattern = '#[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}#i';
184
			if(preg_match_all($pattern, $match[5], $matches)) {
185
				foreach($matches as $submatch) {
186
					foreach($submatch as $value) {
179
				if(!in_array(OUTPUT_FILTER_MODE, array(2,3,6,7))) return $match[0];
180
				// check if last part of the a href link: >xxxx</a> contains a email address we need to filter
181
				$pattern = '#[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}#i';
182
				if(preg_match_all($pattern, $match[5], $matches)) {
183
					foreach($matches as $submatch) {
184
						foreach($submatch as $value) {
187 185
						// replace all . and all @ in email address parts by (dot) and (at) strings
188
						$match[5] = str_replace($value, str_replace($search, $replace, $value), $match[5]);
186
							$match[5] = str_replace($value, str_replace($search, $replace, $value), $match[5]);
187
						}
189 188
					}
190 189
				}
191
			}
192

  
193
			// check if Javascript encryption routine is enabled
194
			if(in_array(OUTPUT_FILTER_MODE, array(6,7))) {
190
				// check if Javascript encryption routine is enabled
191
				if(in_array(OUTPUT_FILTER_MODE, array(6,7))) {
195 192
				/** USE JAVASCRIPT ENCRYPTION FOR MAILTO LINKS **/
196
				
197 193
				// extract possible class and id attribute from ahref link
198
				preg_match('/class\s*?=\s*?("|\')(.*?)\1/ix', $match[0], $class_attr);
199
				$class_attr = empty($class_attr) ? '' : 'class="' . $class_attr[2] . '" ';
200
				preg_match('/id\s*?=\s*?("|\')(.*?)\1/ix', $match[0], $id_attr);
201
				$id_attr = empty($id_attr) ? '' : 'id="' . $id_attr[2] . '" ';
202
				
194
					preg_match('/class\s*?=\s*?("|\')(.*?)\1/ix', $match[0], $class_attr);
195
					$class_attr = empty($class_attr) ? '' : 'class="' . $class_attr[2] . '" ';
196
					preg_match('/id\s*?=\s*?("|\')(.*?)\1/ix', $match[0], $id_attr);
197
					$id_attr = empty($id_attr) ? '' : 'id="' . $id_attr[2] . '" ';
203 198
				// preprocess mailto link parts for further usage
204
				$search = array('@', '.', '_', '-'); $replace = array('F', 'Z', 'X', 'K');
205
				$email_address = str_replace($search, $replace, strtolower($match[2]));
206
				$email_subject = rawurlencode(html_entity_decode($match[3]));
207
				
199
					$search = array('@', '.', '_', '-'); $replace = array('F', 'Z', 'X', 'K');
200
					$email_address = str_replace($search, $replace, strtolower($match[2]));
201
					$email_subject = rawurlencode(html_entity_decode($match[3]));
208 202
				// create a random encryption key for the Caesar cipher
209
				mt_srand((double)microtime()*1000000);	// (PHP < 4.2.0)
210
				$shift = mt_rand(1, 25);
211
				
203
					mt_srand((double)microtime()*1000000);	// (PHP < 4.2.0)
204
					$shift = mt_rand(1, 25);
212 205
				// encrypt the email using an adapted Caesar cipher
213
		  		$encrypted_email = "";
214
				for($i = strlen($email_address) -1; $i > -1; $i--) {
215
					if(preg_match('#[FZXK0-9]#', $email_address[$i], $characters)) {
216
						$encrypted_email .= $email_address[$i];
217
					} else {	
218
						$encrypted_email .= chr((ord($email_address[$i]) -97 + $shift) % 26 + 97);
206
					$encrypted_email = "";
207
					for($i = strlen($email_address) -1; $i > -1; $i--) {
208
						if(preg_match('#[FZXK0-9]#', $email_address[$i], $characters)) {
209
							$encrypted_email .= $email_address[$i];
210
						} else {
211
							$encrypted_email .= chr((ord($email_address[$i]) -97 + $shift) % 26 + 97);
212
						}
219 213
					}
220
				}
221
				$encrypted_email .= chr($shift + 97);
222

  
214
					$encrypted_email .= chr($shift + 97);
223 215
				// build the encrypted Javascript mailto link
224
				$mailto_link  = "<a {$class_attr}{$id_attr}href=\"javascript:mdcr('$encrypted_email','$email_subject')\">" .$match[5] ."</a>";
225
				
226
				return $mailto_link;	
227

  
228
			} else {
216
					$mailto_link  = "<a {$class_attr}{$id_attr}href=\"javascript:mdcr('$encrypted_email','$email_subject')\">" .$match[5] ."</a>";
217
					return $mailto_link;
218
				} else {
229 219
				/** DO NOT USE JAVASCRIPT ENCRYPTION FOR MAILTO LINKS **/
230

  
231
				// as minimum protection, replace replace @ in the mailto part by (at)
220
				// as minimum protection, replace @ in the mailto part by (at)
232 221
				// dots are not transformed as this would transform my.name@domain.com into: my(dot)name(at)domain(dot)com
233
				
234 222
				// rebuild the mailto link from the subpatterns (at the missing characters " and </a>")
235
				return $match[1] .str_replace('@', OUTPUT_FILTER_AT_REPLACEMENT, $match[2]) .$match[3] .'"' .$match[4] .$match[5] .'</a>';
223
					return $match[1] .str_replace('@', OUTPUT_FILTER_AT_REPLACEMENT, $match[2]) .$match[3] .'"' .$match[4] .$match[5] .'</a>';
236 224
				// if you want to protect both, @ and dots, comment out the line above and remove the comment from the line below
237 225
				// return $match[1] .str_replace($search, $replace, $match[2]) .$match[3] .'"' .$match[4] .$match[5] .'</a>';
238
			}
239
		
226
				}
227
			break;
228
			default:
229
		// number of subpatterns do not match the requirements ... do nothing
230
				return $match[0];
231
			break;
240 232
		}
241
		
242
		// number of subpatterns do not match the requirements ... do nothing
243
		return $match[0];
244
	}		
245
}
233
	}
234
/* ************************************************************************** */
branches/2.8.x/wb/modules/output_filter/info.php
4 4
 * @category        modules
5 5
 * @package         output_filter
6 6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
8
 * @copyright       2009-2011, Website Baker Org. e.V.
7
 * @copyright       2011, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11
 * @platform        WebsiteBaker 2.8.x
10
 * @platform        WebsiteBaker 2.8.2
12 11
 * @requirements    PHP 5.2.2 and higher
13 12
 * @version         $Id$
14 13
 * @filesource		$HeadURL$
......
19 18
$module_directory = 'output_filter';
20 19
$module_name = 'Frontend Output Filter';
21 20
$module_function = 'tool';
22
$module_version	= '0.2';
23
$module_platform = '2.7 | 2.8.x';
24
$module_author = 'Christian Sommer (doc)';
21
$module_version	= '0.3';
22
$module_platform = '2.8.2';
23
$module_author = 'Christian Sommer(doc), WB-Project, Werner v.d. Decken(DarkViper)';
25 24
$module_license = 'GNU General Public License';
26 25
$module_description = 'This module allows to filter the output before displaying it on the frontend. Support for filtering mailto links and mail addresses in strings.';
branches/2.8.x/wb/modules/output_filter/tool.php
3 3
 *
4 4
 * @category        modules
5 5
 * @package         output_filter
6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
8
 * @copyright       2009-2011, Website Baker Org. e.V.
6
 * @author          Christian Sommer, WB-Project, Werner v.d. Decken
7
 * @copyright       2011-, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11
 * @platform        WebsiteBaker 2.8.x
10
 * @platform        WebsiteBaker 2.8.2
12 11
 * @requirements    PHP 5.2.2 and higher
13 12
 * @version         $Id$
14 13
 * @filesource		$HeadURL$
15 14
 * @lastmodified    $Date$
16 15
 *
17 16
 */
17
/* -------------------------------------------------------- */
18
// Must include code to stop this file being accessed directly
19
require_once( dirname(dirname(dirname(__FILE__))).'/framework/globalExceptionHandler.php');
20
if(!defined('WB_PATH')) { throw new IllegalFileException(); }
21
/* -------------------------------------------------------- */
18 22

  
19
// Must include code to stop this file being access directly
20
if(defined('WB_PATH') == false) { die("Cannot access this file directly"); }
21

  
22
// check if module language file exists for the language set by the user (e.g. DE, EN)
23
$MOD_MAIL_FILTER['WARNING']	= '<p style="color: red; line-height:1.5em;"><strong>Warning: </strong>This function is now available as a Droplet. The next major release of website baker will not include this filter anymore. Please concider using the <a href="?tool=droplets">Droplet</a> [[EmailFilter]]</p>';
24
if(!file_exists(WB_PATH .'/modules/output_filter/languages/'.LANGUAGE .'.php')) {
25
	// no module language file exists for the language set by the user, include default module language file EN.php
26
	require_once(WB_PATH .'/modules/output_filter/languages/EN.php');
27
} else {
28
	// a module language file exists for the language defined by the user, load it
29
	require_once(WB_PATH .'/modules/output_filter/languages/'.LANGUAGE .'.php');
30
}
23
	$modPath = str_replace('\\', '/', dirname(__FILE__)).'/';
24
	$msgTxt = '';
25
	$msgCls = 'msg-box';
26
// include the modules language definitions
27
	if(!is_readable($modPath.'languages/'.LANGUAGE .'.php')) {
28
		require_once($modPath.'languages/EN.php');
29
	} else {
30
		require_once($modPath.'languages/'.LANGUAGE .'.php');
31
	}
31 32
// check if data was submitted
32
if(isset($_POST['save_settings'])) {
33
	
34
	if (!$admin->checkFTAN())
35
	{
36
		if(!$admin_header) { $admin->print_header(); }
37
		$admin->print_error($MESSAGE['GENERIC_SECURITY_ACCESS'],$_SERVER['REQUEST_URI'],false);
33
	if($doSave) {
34
	// take over post - arguments
35
		$data = array();
36
		$data['sys_rel']       = (int)(intval(isset($_POST['sys_rel']) ? $_POST['sys_rel'] : 0) != 0);
37
		$data['email_filter']  = (int)(intval(isset($_POST['email_filter']) ? $_POST['email_filter'] : 0) != 0);
38
		$data['mailto_filter'] = (int)(intval(isset($_POST['mailto_filter']) ? $_POST['mailto_filter'] : 0) != 0);
39
		$data['at_replacement']  = isset($_POST['at_replacement']) ? trim(strip_tags($_POST['at_replacement'])) : '';
40
		$data['dot_replacement'] = isset($_POST['dot_replacement']) ? trim(strip_tags($_POST['dot_replacement'])) : '';
41
		if ($admin->checkFTAN()) {
42
		// update database settings
43
			$sql = 'UPDATE `'.TABLE_PREFIX.'mod_output_filter` SET '.
44
					  '`email_filter`='.$data['email_filter'].', '.
45
					  '`sys_rel`='.$data['sys_rel'].', '.
46
					  '`mailto_filter`='.$data['mailto_filter'].', '.
47
					  '`at_replacement`=\''.mysql_real_escape_string($data['at_replacement']).'\', '.
48
					  '`dot_replacement`=\''.mysql_real_escape_string($data['dot_replacement']).'\'';
49
			if($database->query($sql)) {
50
			//anything ok
51
				$msgTxt = $MESSAGE['RECORD_MODIFIED_SAVED'];
52
				$msgCls = 'msg-box';
53
			}else {
54
			// database error
55
				$msgTxt = $MESSAGE['RECORD_MODIFIED_FAILED'];
56
				$msgCls = 'error-box';
57
			}
58
		}else {
59
		// FTAN error
60
			$msgTxt = $MESSAGE['GENERIC_SECURITY_ACCESS'];
61
			$msgCls = 'error-box';
62
		}
63
	}else {
64
	// read settings from the database to show
65
		require_once($modPath.'filter-routines.php');
66
		$data = getOutputFilterSettings();
38 67
	}
39
	// get overall output filter settings
40
	$sys_rel = (isset($_POST['sys_rel']) && $_POST['sys_rel'] == '1') ? '1' : '0';
41
	$email_filter = (isset($_POST['email_filter']) && $_POST['email_filter'] == '1') ? '1' : '0';
42
	$mailto_filter = (isset($_POST['mailto_filter']) && $_POST['mailto_filter'] == '1') ? '1' : '0';
43
	
44
	// get email replacement settings
45
	$at_replacement = isset($_POST['at_replacement']) ?strip_tags($_POST['at_replacement']) : '';
46
	$at_replacement = (strlen(trim($at_replacement)) > 0) ? $admin->add_slashes($at_replacement) : '(at)';
47
	$dot_replacement = isset($_POST['dot_replacement']) ?strip_tags($_POST['dot_replacement']) : '';
48
	$dot_replacement = (strlen(trim($dot_replacement)) > 0) ? $admin->add_slashes($dot_replacement) : '(dot)';
49
	
50
	// update database settings
51
	$database->query("UPDATE " .TABLE_PREFIX ."mod_output_filter SET email_filter = '$email_filter',
52
		sys_rel = '$sys_rel', mailto_filter = '$mailto_filter', at_replacement = '$at_replacement', dot_replacement = '$dot_replacement'");
53

  
54
	// check if there is a database error, otherwise say successful
68
	// write out header if needed
55 69
	if(!$admin_header) { $admin->print_header(); }
56
	if($database->is_error()) {
57
		$admin->print_error($database->get_error(), $js_back);
58
	} else {
59
		$admin->print_success($MESSAGE['PAGES']['SAVED'], ADMIN_URL.'/admintools/tool.php?tool=output_filter');
70
	if( $msgTxt != '') {
71
	// write message box if needed
72
		echo '<div class="'.$msgCls.'">'.$msgTxt.'</div>';
60 73
	}
61

  
62
} else {
63
}
64
	// write out heading
65
	echo '<h2>' .$MOD_MAIL_FILTER['HEADING'] .'</h2>';
66

  
67
	// include filter functions
68
	require_once(WB_PATH .'/modules/output_filter/filter-routines.php');
69
	
70
	// read the mail filter settings from the database
71
	$data = get_output_filter_settings();
72
	
73
	// output the form with values from the database
74
	echo '<p>' .$MOD_MAIL_FILTER['HOWTO'] .'</p>';
75
	echo $MOD_MAIL_FILTER['WARNING'];
76 74
?>
75
<h2><?php echo $MOD_MAIL_FILTER['HEADING']; ?></h2>
76
<p><?php echo $MOD_MAIL_FILTER['HOWTO']; ?></p>
77 77
<form name="store_settings" action="<?php echo $_SERVER['REQUEST_URI'];?>" method="post">
78
<?php echo $admin->getFTAN(); ?>
78
	<?php echo $admin->getFTAN(); ?>
79
	<input type="hidden" name="action" value="save" />
79 80
	<table width="98%" cellspacing="0" cellpadding="5px" class="row_a">
80 81
	<tr><td colspan="2"><strong><?php echo $MOD_MAIL_FILTER['BASIC_CONF'];?>:</strong></td></tr>
81 82
	<tr>
......
117 118
			name="dot_replacement"/></td>
118 119
	</tr>
119 120
	</table>
120
	<input type="submit" name="save_settings" style="margin-top:10px; width:140px;" value="<?php echo $TEXT['SAVE']; ?>" />
121
</form>
121
	<input type="submit" style="margin-top:10px; width:140px;" value="<?php echo $TEXT['SAVE']; ?>" />
122
</form>
branches/2.8.x/wb/modules/output_filter/install.php
3 3
 *
4 4
 * @category        modules
5 5
 * @package         output_filter
6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
8
 * @copyright       2009-2011, Website Baker Org. e.V.
6
 * @author          Christian Sommer, WB-Project, Werner v.d. Decken
7
 * @copyright       2011-, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11
 * @platform        WebsiteBaker 2.8.x
10
 * @platform        WebsiteBaker 2.8.2
12 11
 * @requirements    PHP 5.2.2 and higher
13 12
 * @version         $Id$
14 13
 * @filesource		$HeadURL$
15 14
 * @lastmodified    $Date$
16 15
 *
17 16
 */
17
/* -------------------------------------------------------- */
18
// Must include code to stop this file being accessed directly
19
require_once( dirname(dirname(dirname(__FILE__))).'/framework/globalExceptionHandler.php');
20
if(!defined('WB_PATH')) { throw new IllegalFileException(); }
21
/* -------------------------------------------------------- */
18 22

  
19
// Must include code to stop this file being access directly
20
if(defined('WB_PATH') == false) { die("Cannot access this file directly"); }
21

  
22 23
$table = TABLE_PREFIX .'mod_output_filter';
23 24
$database->query("DROP TABLE IF EXISTS `$table`");
24 25

  
25 26
$database->query("CREATE TABLE `$table` (
26
	`sys_rel` VARCHAR(1) NOT NULL DEFAULT '0',
27
	`sys_rel` INT NOT NULL DEFAULT '0',
27 28
	`email_filter` VARCHAR(1) NOT NULL DEFAULT '0',
28 29
	`mailto_filter` VARCHAR(1) NOT NULL DEFAULT '0',
29 30
	`at_replacement` VARCHAR(255) NOT NULL DEFAULT '(at)',
branches/2.8.x/wb/modules/output_filter/index.php
3 3
 *
4 4
 * @category        modules
5 5
 * @package         output_filter
6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
6
 * @author          Christian Sommer, WB-Project, Werner v.d. Decken
8 7
 * @copyright       2009-2011, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11
 * @platform        WebsiteBaker 2.8.x
10
 * @platform        WebsiteBaker 2.8.2
12 11
 * @requirements    PHP 5.2.2 and higher
13 12
 * @version         $Id$
14 13
 * @filesource		$HeadURL$
branches/2.8.x/wb/modules/output_filter/upgrade.php
3 3
 *
4 4
 * @category        modules
5 5
 * @package         output_filter
6
 * @author          WebsiteBaker Project
7
 * @copyright       2004-2009, Ryan Djurovich
6
 * @author          Christian Sommer, WB-Project, Werner v.d. Decken
8 7
 * @copyright       2009-2011, Website Baker Org. e.V.
9 8
 * @link			http://www.websitebaker2.org/
10 9
 * @license         http://www.gnu.org/licenses/gpl.html
11
 * @platform        WebsiteBaker 2.8.x
10
 * @platform        WebsiteBaker 2.8.2
12 11
 * @requirements    PHP 5.2.2 and higher
13 12
 * @version         $Id$
14 13
 * @filesource		$HeadURL$
15 14
 * @lastmodified    $Date$
16 15
 *
17 16
 */
18

  
19
// Must include code to stop this file being access directly
20
if(defined('WB_PATH') == false) { die("Cannot access this file directly"); }
17
/* -------------------------------------------------------- */
18
// Must include code to stop this file being accessed directly
19
require_once( dirname(dirname(dirname(__FILE__))).'/framework/globalExceptionHandler.php');
20
if(!defined('WB_PATH')) { throw new IllegalFileException(); }
21
/* -------------------------------------------------------- */
21 22
global $i;
22 23
$table_name = TABLE_PREFIX .'mod_output_filter';
23 24
$field_name = 'sys_rel';
......
30 31
if ( ($database->field_exists($table_name,$field_name) )) {
31 32
		print "<br /><strong>'Output Filter already updated'</strong> $OK<br />\n";
32 33
} else {
33
	$description = 'VARCHAR(1) NOT NULL DEFAULT \'0\'';
34
	$description = 'INT NOT NULL DEFAULT \'0\' FIRST';
34 35
	if( ($database->field_add($table_name,$field_name,$description )) ) {
35 36
		print "<br /><strong>Updating Output Filter</strong> $OK<br />\n";
36 37
	} else {

Also available in: Unified diff