##############################################################
## MOD Title: 		Zero duplicate 0.4.8 => 0.6.0 update
## MOD Author: 		dcz <n/a> http://www.phpbb-seo.com/
## MOD Description: 	This are the update steps for the phpBB SEO Zero duplicate 0.4.8 => 0.6.0 update.
## 			Check http://www.phpbb-seo.com/en/zero-duplicate/phpbb3-seo-zero-duplicate-t1220.html
## 			for the latest version or to get help with this MOD
##
## MOD Version: 	1.0
##
## Installation Level: 	Eazy
## Installation Time: 	7 Minutes
## Files To Edit: 	5
##			download/file.php,
##			memberlist.php,
##			phpbb_seo/phpbb_seo_class.php (could not be necessary),
##			phpbb_seo/includes/setup_phpbb_seo.php,
##			viewtopic.php.
##
## Included Files: n/a
##############################################################
## Author Notes:
## _____________
##
## This are the update steps for the phpBB3 SEO Zero duplicate 0.4.8 => 0.6.0 update.
##
##############################################################
## MOD History:
##
##	2009-06-08 - 1.0
##		- First version released
##
##############################################################
## Before Adding This MOD To Your Forum, You Should Back Up All Files Related To This MOD
##############################################################


#
#-----[ DIY INSTRUCTIONS ]--------------------------------------------------
#
_________________________________________
>>>>   INSTALLATION INSTRUCTIONS    <<<<<
_________________________________________

This update procedure is very easy and should not cause problem.

#
#-----[ OPEN ]------------------------------------------
#

download/file.php

#
#-----[ FIND ]------------------------------------------
#

// Fetching filename here to prevent sniffing of filename
$sql = 'SELECT attach_id, is_orphan, in_message, post_msg_id, extension, physical_filename, real_filename, mimetype, filetime
	FROM ' . ATTACHMENTS_TABLE . "
	WHERE attach_id = $download_id";

#
#-----[ REPLACE WITH ]------------------------------------------
#

// www.phpBB-SEO.com SEO TOOLKIT BEGIN -> Zero dupe
// Added , attach_comment
// Fetching filename here to prevent sniffing of filename
$sql = 'SELECT attach_id, is_orphan, in_message, post_msg_id, extension, physical_filename, real_filename, mimetype, filetime, attach_comment
	FROM ' . ATTACHMENTS_TABLE . "
	WHERE attach_id = $download_id";
// www.phpBB-SEO.com SEO TOOLKIT END -> Zero dupe

#
#-----[ FIND ]------------------------------------------
#

if ($display_cat == ATTACHMENT_CATEGORY_FLASH && !$user->optionget('viewflash'))
{
	$display_cat = ATTACHMENT_CATEGORY_NONE;
}


#
#-----[ AFTER, ADD ]------------------------------------------
#

// www.phpBB-SEO.com SEO TOOLKIT BEGIN -> Zero dupe
if (!empty($phpbb_seo->seo_opt['rewrite_files'])) {
	if (empty($phpbb_seo->seo_url['file'][$download_id])) {
		$comment = bbcode_nl2br(censor_text($attachment['attach_comment']));
		$comment_clean = preg_replace('`<[^>]*>`Ui', ' ', $comment);
		$_display_cat =  ($thumbnail && $display_cat != ATTACHMENT_CATEGORY_NONE) ? ATTACHMENT_CATEGORY_THUMB : $display_cat;
		if (($_pos = utf8_strpos($comment, '<br')) !== false) {
			$comment_url = strip_tags(utf8_substr($comment, 0, $_pos));
		} else {
			$comment_url = $comment_clean;
		}
		$comment_url = utf8_strlen($comment_url) > 60 ? utf8_substr($comment_url, 0, 60) : $comment_url; 
		$phpbb_seo->seo_url['file'][$download_id] = $phpbb_seo->format_url($comment_url, $phpbb_seo->seo_static['file'][$display_cat]);
	}
	$phpbb_seo->seo_opt['zero_dupe']['redir_def'] = array(
		'id' => array('val' => $download_id, 'keep' => true),
		'mode' => array('val' => $mode, 'keep' => (boolean) ($mode == 'view')),
		't' => array('val' => $thumbnail, 'keep' => $thumbnail),
	);
	$phpbb_seo->seo_chk_dupe('', '', $phpbb_root_path . 'download/');
}
// www.phpBB-SEO.com SEO TOOLKIT END -> Zero dupe

#
#-----[ OPEN ]------------------------------------------
#

memberlist.php

#
#-----[ FIND ]------------------------------------------
#
		if ($mode == 'group') {
			if ( empty($phpbb_seo->seo_url['group'][$group_row['group_id']]) ) {
				$phpbb_seo->seo_url['group'][$group_row['group_id']] = $phpbb_seo->format_url($group_row['group_name'], $phpbb_seo->seo_static['group']);
			}
#
#-----[ REPLACE WITH ]------------------------------------------
#
		if ($mode == 'group') {
			$phpbb_seo->prepare_url('group', $group_row['group_name'], $group_row['group_id']);

#
#-----[ OPEN ]------------------------------------------
#

phpbb_seo/phpbb_seo_class.php

#
#-----[ FIND ]------------------------------------------
#

		// --> Zero Dupe
		$this->seo_opt['zero_dupe'] = array( 'on' => false, // Activate or not the redirections : true / false
			'strict' => false, // strict compare, == VS strpos() : true / false
			'post_redir' => 'guest', // Redirect post urls if not valid ? : guest / all / post / off
		);
		$this->cache_config['dynamic_options']['zero_dupe'] = $this->seo_opt['zero_dupe']; // Do not change
		$this->seo_opt['zero_dupe']['do_redir'] = false; // do not change
		$this->seo_opt['zero_dupe']['go_redir'] = true; // do not change
		$this->seo_opt['zero_dupe']['do_redir_post'] = false; // do not change
		$this->seo_opt['zero_dupe']['start'] = 0; // do not change
		$this->seo_opt['zero_dupe']['redir_def'] = array(); // do not change
		// <-- Zero Dupe

#
#-----[ REPLACE WITH ]------------------------------------------
# EG DELETE

#
#-----[ FIND ]------------------------------------------
#
	// --> Zero Duplicate
	/**
	* Custom HTTP 301 redirections.
	* To kill duplicates
	*/
	function seo_redirect($url, $header = '301 Moved Permanently', $code = 301, $replace = TRUE) {
		global $db;
		if (!$this->seo_opt['zero_dupe']['on'] || headers_sent()) {
			return false;
		}
		garbage_collection();
		$url = str_replace('&amp;', '&', $url);
		// Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2
		if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false) {
			trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
		}
		$http = 'HTTP/1.1 ';
		header($http . $header, $replace, $code);
		header('Location: ' . $url);
		exit_handler();
	}
	/**
	* Set the do_redir_post option right
	*/
	function set_do_redir_post() {
		global $user;
		switch ($this->seo_opt['zero_dupe']['post_redir']) {
			case 'guest':
				if ( empty($user->data['is_registered']) ) {
					$this->seo_opt['zero_dupe']['do_redir_post'] = true;
				}
				break;
			case 'all':
				$this->seo_opt['zero_dupe']['do_redir_post'] = true;
				break;
			case 'off': // Do not redirect
				$this->seo_opt['zero_dupe']['do_redir'] = false;
				$this->seo_opt['zero_dupe']['go_redir'] = false;
				$this->seo_opt['zero_dupe']['do_redir_post'] = false;
				break;
			default:
				$this->seo_opt['zero_dupe']['do_redir_post'] = false;
				break;	
		}
		return $this->seo_opt['zero_dupe']['do_redir_post'];
	}
	/**
	* Redirects if the uri sent does not match (fully) the 
	* attended url
	*/
	function seo_chk_dupe($url = '', $uri = '', $path = '') {
		global $auth, $user, $_SID, $phpbb_root_path;
		static $global_defs;
		if (empty($this->seo_opt['req_file']) || (!$this->seo_opt['rewrite_usermsg'] && $this->seo_opt['req_file'] == 'search') ) {
			return false;
		}
		$path = empty($path) ? $phpbb_root_path : $path;
		$uri = !empty($uri) ? $uri : $this->seo_path['uri'];
		$reg = !empty($user->data['is_registered']) ? true : false;
		if (empty($global_defs)) {
			$global_defs = array(
				'sid' => array('val' => $_SID, 'keep' => $reg ? (boolean) !empty($_SID) :  (boolean) ( !empty($_SID) ? ($this->seo_opt['rem_sid'] ? false : true) : false)),
				'explain' => array('val' => 1, 'keep' => $reg ? (boolean) ($auth->acl_get('a_') && defined('DEBUG_EXTRA')) : false),
			);
		}
		$this->seo_opt['zero_dupe']['redir_def'] = array_merge($this->seo_opt['zero_dupe']['redir_def'], $global_defs);
		$this->set_cond(!empty($_REQUEST['sid']) && ($_REQUEST['sid'] != $user->session_id || (!$reg && $this->seo_opt['rem_sid'])), 'do_redir');
		if (empty($url)) {;
			$url = $this->expected_url($path);
		} else {
			$url = str_replace('&amp;', '&', append_sid($url, false, true, 0));
			if (!empty($_SID) && $global_defs['sid']['keep']) {
				$url .=  (utf8_strpos( $url, '?' ) !== false ? '&' : '?') . 'sid=' . $_SID;
			}
			if (isset($_REQUEST['explain']) && $global_defs['explain']['keep']) {
				$url .= (utf8_strpos( $url, '?' ) !== false ? '&' : '?') . 'explain=1';
			}
		}
		$url = str_replace( '%26', '&', urldecode($url));
		if ($this->seo_opt['zero_dupe']['do_redir']) {
			$this->seo_redirect($url);
		} elseif ($this->seo_opt['zero_dupe']['strict']) {
			return $this->seo_opt['zero_dupe']['go_redir'] && ( ($uri != $url) ? $this->seo_redirect($url) : false );
		} else {
			return $this->seo_opt['zero_dupe']['go_redir'] && ( (utf8_strpos( $uri, $url ) === false) ? $this->seo_redirect($url) : false );
		}
	}
	/**
	* expected_url($path = '')
	* build expected url
	*/
	function expected_url($path = '') {
		global $phpbb_root_path, $phpEx;
		$path = empty($path) ? $phpbb_root_path : $path;
		$params = array();
		foreach ($this->seo_opt['zero_dupe']['redir_def'] as $get => $def) {
			if ((isset($_REQUEST[$get]) && $def['keep']) || !empty($def['force'])) {
				$params[$get] = $def['val'];
			}
		}
		$this->page_url = append_sid($path . $this->seo_opt['req_file'] . ".$phpEx", $params, false, 0);
		return $this->page_url;
	}
	/**
	* set_cond($bool, $type = 'bool_redir', $or = true)
	* Helps out grabbing boolean vars
	*/
	function set_cond($bool, $type = 'do_redir', $or = true) {
		if ( $or ) {
			$this->seo_opt['zero_dupe'][$type] = (boolean) ($bool || $this->seo_opt['zero_dupe'][$type]);
		} else {
			$this->seo_opt['zero_dupe'][$type] = (boolean) ($bool && $this->seo_opt['zero_dupe'][$type]);
		}
		return;
	}
	/**
	* check start var consistency
	* and return our best guess for $start, eg the first valid page 
	* parameter according to pagination settings being lower
	* than the one sent.
	*/
	function seo_chk_start($start = 0, $limit = 0) {
		if ($limit > 0) {
			$start = is_int($start/$limit) ? $start : intval($start/$limit)*$limit;
		}
		if ( $start >= 1 ) {
			$this->start = $this->seo_delim['start'] . (int) $start;
			return (int) $start;
		}
		$this->start = '';
		return 0;
	}
	// <-- Zero Duplicate
#
#-----[ REPLACE WITH ]------------------------------------------
# EG DELETE

#
#-----[ OPEN ]------------------------------------------
#

phpbb_seo/includes/setup_phpbb_seo.php

#
#-----[ FIND ]------------------------------------------
#
	function init_phpbb_seo() {
		global $phpEx, $config, $phpbb_root_path;
#
#-----[ AFTER, ADD ]------------------------------------------
#

		// --> Zero Dupe
		$this->seo_opt['zero_dupe'] = array( 'on' => false, // Activate or not the redirections : true / false
			'strict' => false, // strict compare, == VS strpos() : true / false
			'post_redir' => 'guest', // Redirect post urls if not valid ? : guest / all / post / off
		);
		$this->cache_config['dynamic_options']['zero_dupe'] = $this->seo_opt['zero_dupe']; // Do not change
		$this->seo_opt['zero_dupe']['do_redir'] = false; // do not change
		$this->seo_opt['zero_dupe']['go_redir'] = true; // do not change
		$this->seo_opt['zero_dupe']['do_redir_post'] = false; // do not change
		$this->seo_opt['zero_dupe']['start'] = 0; // do not change
		$this->seo_opt['zero_dupe']['redir_def'] = array(); // do not change
		// <-- Zero Dupe

#
#-----[ FIND ]------------------------------------------
#

		// Let's make sure that settings are consistent
		$this->check_config();
	}
	// Here start the add-on methods

#
#-----[ AFTER, ADD ]------------------------------------------
#

	// --> Zero Duplicate
	/**
	* Custom HTTP 301 redirections.
	* To kill duplicates
	*/
	function seo_redirect($url, $header = '301 Moved Permanently', $code = 301, $replace = true) {
		global $db;
		if (!$this->seo_opt['zero_dupe']['on'] || @headers_sent()) {
			return false;
		}
		garbage_collection();
		$url = str_replace('&amp;', '&', $url);
		// Behave as redirect() for checks to provide with the same level of protection
		// Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2
		if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false) {
			trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
		}
		// Now, also check the protocol and for a valid url the last time...
		$allowed_protocols = array('http', 'https'/*, 'ftp', 'ftps'*/);
		$url_parts = parse_url($url);
		if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols)) {
			trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
		}
		$http = 'HTTP/1.1 ';
		header($http . $header, $replace, $code);
		header('Location: ' . $url);
		exit_handler();
	}
	/**
	* Set the do_redir_post option right
	*/
	function set_do_redir_post() {
		global $user;
		switch ($this->seo_opt['zero_dupe']['post_redir']) {
			case 'guest':
				if ( empty($user->data['is_registered']) ) {
					$this->seo_opt['zero_dupe']['do_redir_post'] = true;
				}
				break;
			case 'all':
				$this->seo_opt['zero_dupe']['do_redir_post'] = true;
				break;
			case 'off': // Do not redirect
				$this->seo_opt['zero_dupe']['do_redir'] = false;
				$this->seo_opt['zero_dupe']['go_redir'] = false;
				$this->seo_opt['zero_dupe']['do_redir_post'] = false;
				break;
			default:
				$this->seo_opt['zero_dupe']['do_redir_post'] = false;
				break;	
		}
		return $this->seo_opt['zero_dupe']['do_redir_post'];
	}
	/**
	* Redirects if the uri sent does not match (fully) the 
	* attended url
	*/
	function seo_chk_dupe($url = '', $uri = '', $path = '') {
		global $auth, $user, $_SID, $phpbb_root_path, $config;
		if (empty($this->seo_opt['req_file']) || (!$this->seo_opt['rewrite_usermsg'] && $this->seo_opt['req_file'] == 'search') ) {
			return false;
		}
		if (!empty($_REQUEST['explain']) && (boolean) ($auth->acl_get('a_') && defined('DEBUG_EXTRA'))) {
			if ($_REQUEST['explain'] == 1) {
				return true;
			}
		}
		$path = empty($path) ? $phpbb_root_path : $path;
		$uri = !empty($uri) ? $uri : $this->seo_path['uri'];
		$reg = !empty($user->data['is_registered']) ? true : false;
		$url = empty($url) ? $this->expected_url($path) : str_replace('&amp;', '&', append_sid($url, false, true, 0));
		$url = $this->drop_sid($url);
		// Only add sid if user is registered and needs it to keep session
		if (!empty($_GET['sid']) && !empty($_SID) && ($reg || !$this->seo_opt['rem_sid']) ) {
			if ($_GET['sid'] == $user->session_id) {
				$url .=  (utf8_strpos( $url, '?' ) !== false ? '&' : '?') . 'sid=' . $user->session_id;
			}
		}
		$url = str_replace( '%26', '&', urldecode($url));
		if ($this->seo_opt['zero_dupe']['do_redir']) {
			$this->seo_redirect($url);
		} else {
			$url_check = $url;
			// we remove url hash for comparison, but keep it for redirect
			if (strpos($url, '#') !== false) {
				list($url_check, $hash) = explode('#', $url, 2);
			}
			if ($this->seo_opt['zero_dupe']['strict']) {
				return $this->seo_opt['zero_dupe']['go_redir'] && ( ($uri != $url_check) ? $this->seo_redirect($url) : false );
			} else {
				return $this->seo_opt['zero_dupe']['go_redir'] && ( (utf8_strpos( $uri, $url_check ) === false) ? $this->seo_redirect($url) : false );
			}
		}
	}
	/**
	* expected_url($path = '')
	* build expected url
	*/
	function expected_url($path = '') {
		global $phpbb_root_path, $phpEx;
		$path = empty($path) ? $phpbb_root_path : $path;
		$params = array();
		foreach ($this->seo_opt['zero_dupe']['redir_def'] as $get => $def) {
			if ((isset($_GET[$get]) && $def['keep']) || !empty($def['force'])) {
				$params[$get] = $def['val'];
				if (!empty($def['hash'])) {
					$params['#'] = $def['hash'];
				}
			}
		}
		$this->page_url = append_sid($path . $this->seo_opt['req_file'] . ".$phpEx", $params, false, 0);
		return $this->page_url;
	}
	/**
	* set_cond($bool, $type = 'bool_redir', $or = true)
	* Helps out grabbing boolean vars
	*/
	function set_cond($bool, $type = 'do_redir', $or = true) {
		if ( $or ) {
			$this->seo_opt['zero_dupe'][$type] = (boolean) ($bool || $this->seo_opt['zero_dupe'][$type]);
		} else {
			$this->seo_opt['zero_dupe'][$type] = (boolean) ($bool && $this->seo_opt['zero_dupe'][$type]);
		}
		return;
	}
	/**
	* check start var consistency
	* Returns our best guess for $start, eg the first valid page
	*/
	function seo_chk_start($start = 0, $limit = 0) {
		if ($limit > 0) {
			$start = is_int($start/$limit) ? $start : intval($start/$limit)*$limit;
		}
		if ( $start >= 1 ) {
			$this->start = $this->seo_delim['start'] . (int) $start;
			return (int) $start;
		}
		$this->start = '';
		return 0;
	}
	// <-- Zero Duplicate
#
#-----[ OPEN ]------------------------------------------
#

viewtopic.php

#
#-----[ FIND ]------------------------------------------
#
		'p' => array('val' => $post_id, 'keep' => true, 'force' => true),
		'hilit' => array('val' => (($highlight_match) ? $highlight : ''), 'keep' => !empty($highlight)),
#
#-----[ REPLACE WITH ]------------------------------------------
#
		'p' => array('val' => $post_id, 'keep' => true, 'force' => true, 'hash' => "p$post_id"),
		'hilit' => array('val' => (($highlight_match) ? $highlight : ''), 'keep' => !empty($highlight_match)),
#
#-----[ FIND ]------------------------------------------
#
		't' => array('val' => $topic_id, 'keep' => true, 'force' => true),
		'p' => array('val' => $post_id, 'keep' =>  ($view == 'show' ? true : false)),
#
#-----[ REPLACE WITH ]------------------------------------------
#
		't' => array('val' => $topic_id, 'keep' => true, 'force' => true, 'hash' => $post_id ? "p$post_id" : ''),
		'p' => array('val' => $post_id, 'keep' =>  ($post_id && $view == 'show' ? true : false), 'hash' => "p$post_id"),
#
#-----[ SAVE/CLOSE ALL FILES ]------------------------------------------
#
# EoM
