includes/pageutils.php
changeset 1227 bdac73ed481e
parent 1216 4125e19d3b27
child 1252 e34c23a35dc9
equal deleted inserted replaced
1226:de56132c008d 1227:bdac73ed481e
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    13  */
    13  */
    14  
    14  
    15 class PageUtils {
    15 class PageUtils {
    16   
    16 	
    17   /**
    17 	/**
    18    * Tell if a username is used or not.
    18  	* Tell if a username is used or not.
    19    * @param $name the name to check for
    19  	* @param $name the name to check for
    20    * @return string
    20  	* @return string
    21    */
    21  	*/
    22   
    22 	
    23   public static function checkusername($name)
    23 	public static function checkusername($name)
    24   {
    24 	{
    25     global $db, $session, $paths, $template, $plugins; // Common objects
    25 		global $db, $session, $paths, $template, $plugins; // Common objects
    26     $name = str_replace('_', ' ', $name);
    26 		$name = str_replace('_', ' ', $name);
    27     $q = $db->sql_query('SELECT username FROM ' . table_prefix.'users WHERE username=\'' . $db->escape(rawurldecode($name)) . '\'');
    27 		$q = $db->sql_query('SELECT username FROM ' . table_prefix.'users WHERE username=\'' . $db->escape(rawurldecode($name)) . '\'');
    28     if ( !$q )
    28 		if ( !$q )
    29     {
    29 		{
    30       die($db->get_error());
    30 			die($db->get_error());
    31     }
    31 		}
    32     if ( $db->numrows() < 1)
    32 		if ( $db->numrows() < 1)
    33     {
    33 		{
    34       $db->free_result(); return('good');
    34 			$db->free_result(); return('good');
    35     }
    35 		}
    36     else
    36 		else
    37     {
    37 		{
    38       $db->free_result(); return('bad');
    38 			$db->free_result(); return('bad');
    39     }
    39 		}
    40   }
    40 	}
    41   
    41 	
    42   /**
    42 	/**
    43    * Get the wiki formatting source for a page
    43  	* Get the wiki formatting source for a page
    44    * @param $page the full page id (Namespace:Pagename)
    44  	* @param $page the full page id (Namespace:Pagename)
    45    * @return string
    45  	* @return string
    46    * @todo (DONE) Make it require a password (just for security purposes)
    46  	* @todo (DONE) Make it require a password (just for security purposes)
    47    */
    47  	*/
    48    
    48  	
    49   public static function getsource($page, $password = false)
    49 	public static function getsource($page, $password = false)
    50   {
    50 	{
    51     global $db, $session, $paths, $template, $plugins; // Common objects
    51 		global $db, $session, $paths, $template, $plugins; // Common objects
    52     if ( !isPage($page) )
    52 		if ( !isPage($page) )
    53     {
    53 		{
    54       return '';
    54 			return '';
    55     }
    55 		}
    56     
    56 		
    57     list($page_id, $namespace) = RenderMan::strToPageID($page);
    57 		list($page_id, $namespace) = RenderMan::strToPageID($page);
    58     $ns = namespace_factory($page_id, $namespace);
    58 		$ns = namespace_factory($page_id, $namespace);
    59     $cdata = $ns->get_cdata();
    59 		$cdata = $ns->get_cdata();
    60     
    60 		
    61     if ( strlen($cdata['password']) == 40 )
    61 		if ( strlen($cdata['password']) == 40 )
    62     {
    62 		{
    63       if(!$password || ( $password != $cdata['password']))
    63 			if(!$password || ( $password != $cdata['password']))
    64       {
    64 			{
    65         return 'invalid_password';
    65 				return 'invalid_password';
    66       }
    66 			}
    67     }
    67 		}
    68     
    68 		
    69     if(!$session->get_permissions('view_source')) // Dependencies handle this for us - this also checks for read privileges
    69 		if(!$session->get_permissions('view_source')) // Dependencies handle this for us - this also checks for read privileges
    70       return 'access_denied';
    70 			return 'access_denied';
    71     $pid = RenderMan::strToPageID($page);
    71 		$pid = RenderMan::strToPageID($page);
    72     if($pid[1] == 'Special' || $pid[1] == 'Admin')
    72 		if($pid[1] == 'Special' || $pid[1] == 'Admin')
    73     {
    73 		{
    74       die('This type of page (' . $paths->nslist[$pid[1]] . ') cannot be edited because the page source code is not stored in the database.');
    74 			die('This type of page (' . $paths->nslist[$pid[1]] . ') cannot be edited because the page source code is not stored in the database.');
    75     }
    75 		}
    76     
    76 		
    77     $e = $db->sql_query('SELECT page_text,char_tag FROM ' . table_prefix.'page_text WHERE page_id=\'' . $pid[0] . '\' AND namespace=\'' . $pid[1] . '\'');
    77 		$e = $db->sql_query('SELECT page_text,char_tag FROM ' . table_prefix.'page_text WHERE page_id=\'' . $pid[0] . '\' AND namespace=\'' . $pid[1] . '\'');
    78     if ( !$e )
    78 		if ( !$e )
    79     {
    79 		{
    80       $db->_die('The page text could not be selected.');
    80 			$db->_die('The page text could not be selected.');
    81     }
    81 		}
    82     if( $db->numrows() < 1 )
    82 		if( $db->numrows() < 1 )
    83     {
    83 		{
    84       return ''; //$db->_die('There were no rows in the text table that matched the page text query.');
    84 			return ''; //$db->_die('There were no rows in the text table that matched the page text query.');
    85     }
    85 		}
    86     
    86 		
    87     $r = $db->fetchrow();
    87 		$r = $db->fetchrow();
    88     $db->free_result();
    88 		$db->free_result();
    89     $message = $r['page_text'];
    89 		$message = $r['page_text'];
    90     
    90 		
    91     return htmlspecialchars($message);
    91 		return htmlspecialchars($message);
    92   }
    92 	}
    93   
    93 	
    94   /**
    94 	/**
    95    * DEPRECATED. Previously returned the full rendered contents of a page.
    95  	* DEPRECATED. Previously returned the full rendered contents of a page.
    96    * @param $page the full page id (Namespace:Pagename)
    96  	* @param $page the full page id (Namespace:Pagename)
    97    * @param $send_headers true if the theme headers should be sent (still dependent on current page settings), false otherwise
    97  	* @param $send_headers true if the theme headers should be sent (still dependent on current page settings), false otherwise
    98    * @return string
    98  	* @return string
    99    */
    99  	*/
   100   
   100 	
   101   public static function getpage($page, $send_headers = false, $hist_id = false)
   101 	public static function getpage($page, $send_headers = false, $hist_id = false)
   102   {
   102 	{
   103     die('PageUtils->getpage is deprecated.');
   103 		die('PageUtils->getpage is deprecated.');
   104   }
   104 	}
   105   
   105 	
   106   /**
   106 	/**
   107    * Writes page data to the database, after verifying permissions and running the XSS filter
   107  	* Writes page data to the database, after verifying permissions and running the XSS filter
   108    * @param $page_id the page ID
   108  	* @param $page_id the page ID
   109    * @param $namespace the namespace
   109  	* @param $namespace the namespace
   110    * @param $message the text to save
   110  	* @param $message the text to save
   111    * @return string
   111  	* @return string
   112    */
   112  	*/
   113    
   113  	
   114   public static function savepage($page_id, $namespace, $message, $summary = 'No edit summary given', $minor = false)
   114 	public static function savepage($page_id, $namespace, $message, $summary = 'No edit summary given', $minor = false)
   115   {
   115 	{
   116     global $db, $session, $paths, $template, $plugins; // Common objects
   116 		global $db, $session, $paths, $template, $plugins; // Common objects
   117     
   117 		
   118     $page = new PageProcessor($page_id, $namespace);
   118 		$page = new PageProcessor($page_id, $namespace);
   119     $cdata = $page->ns->get_cdata();
   119 		$cdata = $page->ns->get_cdata();
   120     return $page->update_page($message, $summary, $minor, $cdata['page_format']);
   120 		return $page->update_page($message, $summary, $minor, $cdata['page_format']);
   121   }
   121 	}
   122   
   122 	
   123   /**
   123 	/**
   124    * Creates a page, both in memory and in the database.
   124  	* Creates a page, both in memory and in the database.
   125    * @param string $page_id
   125  	* @param string $page_id
   126    * @param string $namespace
   126  	* @param string $namespace
   127    * @return bool true on success, false on failure
   127  	* @return bool true on success, false on failure
   128    */
   128  	*/
   129   
   129 	
   130   public static function createPage($page_id, $namespace, $name = false, $visible = 1)
   130 	public static function createPage($page_id, $namespace, $name = false, $visible = 1)
   131   {
   131 	{
   132     global $db, $session, $paths, $template, $plugins; // Common objects
   132 		global $db, $session, $paths, $template, $plugins; // Common objects
   133     if(in_array($namespace, Array('Special', 'Admin')))
   133 		if(in_array($namespace, Array('Special', 'Admin')))
   134     {
   134 		{
   135       // echo '<b>Notice:</b> PageUtils::createPage: You can\'t create a special page in the database<br />';
   135 			// echo '<b>Notice:</b> PageUtils::createPage: You can\'t create a special page in the database<br />';
   136       return 'You can\'t create a special page in the database';
   136 			return 'You can\'t create a special page in the database';
   137     }
   137 		}
   138     
   138 		
   139     if(!isset($paths->nslist[$namespace]))
   139 		if(!isset($paths->nslist[$namespace]))
   140     {
   140 		{
   141       // echo '<b>Notice:</b> PageUtils::createPage: Couldn\'t look up the namespace<br />';
   141 			// echo '<b>Notice:</b> PageUtils::createPage: Couldn\'t look up the namespace<br />';
   142       return 'Couldn\'t look up the namespace';
   142 			return 'Couldn\'t look up the namespace';
   143     }
   143 		}
   144     
   144 		
   145     $pname = $paths->nslist[$namespace] . $page_id;
   145 		$pname = $paths->nslist[$namespace] . $page_id;
   146     if(isPage($pname))
   146 		if(isPage($pname))
   147     {
   147 		{
   148       // echo '<b>Notice:</b> PageUtils::createPage: Page already exists<br />';
   148 			// echo '<b>Notice:</b> PageUtils::createPage: Page already exists<br />';
   149       return 'Page already exists';
   149 			return 'Page already exists';
   150     }
   150 		}
   151     
   151 		
   152     if(!$session->get_permissions('create_page'))
   152 		if(!$session->get_permissions('create_page'))
   153     {
   153 		{
   154       // echo '<b>Notice:</b> PageUtils::createPage: Not authorized to create pages<br />';
   154 			// echo '<b>Notice:</b> PageUtils::createPage: Not authorized to create pages<br />';
   155       return 'Not authorized to create pages';
   155 			return 'Not authorized to create pages';
   156     }
   156 		}
   157     
   157 		
   158     if($session->user_level < USER_LEVEL_ADMIN && $namespace == 'System')
   158 		if($session->user_level < USER_LEVEL_ADMIN && $namespace == 'System')
   159     {
   159 		{
   160       // echo '<b>Notice:</b> PageUtils::createPage: Not authorized to create system messages<br />';
   160 			// echo '<b>Notice:</b> PageUtils::createPage: Not authorized to create system messages<br />';
   161       return 'Not authorized to create system messages';
   161 			return 'Not authorized to create system messages';
   162     }
   162 		}
   163     
   163 		
   164     if ( substr($page_id, 0, 8) == 'Project:' )
   164 		if ( substr($page_id, 0, 8) == 'Project:' )
   165     {
   165 		{
   166       // echo '<b>Notice:</b> PageUtils::createPage: Prefix "Project:" is reserved<br />';
   166 			// echo '<b>Notice:</b> PageUtils::createPage: Prefix "Project:" is reserved<br />';
   167       return 'The prefix "Project:" is reserved for a parser shortcut; if a page was created using this prefix, it would not be possible to link to it.';
   167 			return 'The prefix "Project:" is reserved for a parser shortcut; if a page was created using this prefix, it would not be possible to link to it.';
   168     }
   168 		}
   169     
   169 		
   170     /*
   170 		/*
   171     // Dunno why this was here. Enano can handle more flexible names than this...
   171 		// Dunno why this was here. Enano can handle more flexible names than this...
   172     $regex = '#^([A-z0-9 _\-\.\/\!\@\(\)]*)$#is';
   172 		$regex = '#^([A-z0-9 _\-\.\/\!\@\(\)]*)$#is';
   173     if(!preg_match($regex, $name))
   173 		if(!preg_match($regex, $name))
   174     {
   174 		{
   175       //echo '<b>Notice:</b> PageUtils::createPage: Name contains invalid characters<br />';
   175 			//echo '<b>Notice:</b> PageUtils::createPage: Name contains invalid characters<br />';
   176       return 'Name contains invalid characters';
   176 			return 'Name contains invalid characters';
   177     }
   177 		}
   178     */
   178 		*/
   179     
   179 		
   180     $page_id = dirtify_page_id($page_id);
   180 		$page_id = dirtify_page_id($page_id);
   181     
   181 		
   182     if ( !$name )
   182 		if ( !$name )
   183       $name = str_replace('_', ' ', $page_id);
   183 			$name = str_replace('_', ' ', $page_id);
   184     
   184 		
   185     $page_id = sanitize_page_id( $page_id );
   185 		$page_id = sanitize_page_id( $page_id );
   186     
   186 		
   187     $prot = ( $namespace == 'System' ) ? 1 : 0;
   187 		$prot = ( $namespace == 'System' ) ? 1 : 0;
   188     
   188 		
   189     $ips = array(
   189 		$ips = array(
   190       'ip' => array(),
   190 			'ip' => array(),
   191       'u' => array()
   191 			'u' => array()
   192       );
   192 			);
   193     
   193 		
   194     $page_data = Array(
   194 		$page_data = Array(
   195       'name'=>$name,
   195 			'name'=>$name,
   196       'urlname'=>$page_id,
   196 			'urlname'=>$page_id,
   197       'namespace'=>$namespace,
   197 			'namespace'=>$namespace,
   198       'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>$prot,'delvotes'=>0,'delvote_ips'=>serialize($ips),'wiki_mode'=>2,
   198 			'special'=>0,'visible'=>1,'comments_on'=>0,'protected'=>$prot,'delvotes'=>0,'delvote_ips'=>serialize($ips),'wiki_mode'=>2,
   199     );
   199 		);
   200     
   200 		
   201     // die('PageUtils::createpage: Creating page with this data:<pre>' . print_r($page_data, true) . '</pre>');
   201 		// die('PageUtils::createpage: Creating page with this data:<pre>' . print_r($page_data, true) . '</pre>');
   202     
   202 		
   203     $paths->add_page($page_data);
   203 		$paths->add_page($page_data);
   204     
   204 		
   205     $qa = $db->sql_query('INSERT INTO ' . table_prefix.'pages(name,urlname,namespace,visible,protected,delvote_ips) VALUES(\'' . $db->escape($name) . '\', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\', '. ( $visible ? '1' : '0' ) .', ' . $prot . ', \'' . $db->escape(serialize($ips)) . '\');');
   205 		$qa = $db->sql_query('INSERT INTO ' . table_prefix.'pages(name,urlname,namespace,visible,protected,delvote_ips) VALUES(\'' . $db->escape($name) . '\', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\', '. ( $visible ? '1' : '0' ) .', ' . $prot . ', \'' . $db->escape(serialize($ips)) . '\');');
   206     $qb = $db->sql_query('INSERT INTO ' . table_prefix.'page_text(page_id,namespace) VALUES(\'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
   206 		$qb = $db->sql_query('INSERT INTO ' . table_prefix.'page_text(page_id,namespace) VALUES(\'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
   207     $qc = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,author_uid,page_id,namespace) VALUES('.time().', \'DEPRECATED\', \'page\', \'create\', \'' . $session->username . '\', ' . $session->user_id . ', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
   207 		$qc = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,author_uid,page_id,namespace) VALUES('.time().', \'DEPRECATED\', \'page\', \'create\', \'' . $session->username . '\', ' . $session->user_id . ', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
   208     
   208 		
   209     if($qa && $qb && $qc)
   209 		if($qa && $qb && $qc)
   210       return 'good';
   210 			return 'good';
   211     else
   211 		else
   212     {
   212 		{
   213       return $db->get_error();
   213 			return $db->get_error();
   214     }
   214 		}
   215   }
   215 	}
   216   
   216 	
   217   /**
   217 	/**
   218    * Sets the protection level on a page.
   218  	* Sets the protection level on a page.
   219    * @param $page_id string the page ID
   219  	* @param $page_id string the page ID
   220    * @param $namespace string the namespace
   220  	* @param $namespace string the namespace
   221    * @param $level int level of protection - 0 is off, 1 is full, 2 is semi
   221  	* @param $level int level of protection - 0 is off, 1 is full, 2 is semi
   222    * @param $reason string why the page is being (un)protected
   222  	* @param $reason string why the page is being (un)protected
   223    * @return string - "good" on success, in all other cases, an error string (on query failure, calls $db->_die() )
   223  	* @return string - "good" on success, in all other cases, an error string (on query failure, calls $db->_die() )
   224    */
   224  	*/
   225   public static function protect($page_id, $namespace, $level, $reason)
   225 	public static function protect($page_id, $namespace, $level, $reason)
   226   {
   226 	{
   227     global $db, $session, $paths, $template, $plugins; // Common objects
   227 		global $db, $session, $paths, $template, $plugins; // Common objects
   228     
   228 		
   229     $page = new PageProcessor($page_id, $namespace);
   229 		$page = new PageProcessor($page_id, $namespace);
   230     return $page->protect_page($level, $reason);
   230 		return $page->protect_page($level, $reason);
   231   }
   231 	}
   232   
   232 	
   233   /**
   233 	/**
   234    * Generates an HTML table with history information in it.
   234  	* Generates an HTML table with history information in it.
   235    * @param string the page ID
   235  	* @param string the page ID
   236    * @param string the namespace
   236  	* @param string the namespace
   237    * @param string page password
   237  	* @param string page password
   238    * @return string
   238  	* @return string
   239    */
   239  	*/
   240   
   240 	
   241   public static function histlist($page_id, $namespace, $password = false)
   241 	public static function histlist($page_id, $namespace, $password = false)
   242   {
   242 	{
   243     global $db, $session, $paths, $template, $plugins; // Common objects
   243 		global $db, $session, $paths, $template, $plugins; // Common objects
   244     global $lang;
   244 		global $lang;
   245     
   245 		
   246     if(!$session->get_permissions('history_view'))
   246 		if(!$session->get_permissions('history_view'))
   247       return 'Access denied';
   247 			return 'Access denied';
   248     
   248 		
   249     ob_start();
   249 		ob_start();
   250     
   250 		
   251     $pname = $paths->get_pathskey($page_id, $namespace);
   251 		$pname = $paths->get_pathskey($page_id, $namespace);
   252     $ns = namespace_factory($page_id, $namespace);
   252 		$ns = namespace_factory($page_id, $namespace);
   253     $cdata = $ns->get_cdata();
   253 		$cdata = $ns->get_cdata();
   254     
   254 		
   255     if ( !isPage($pname) )
   255 		if ( !isPage($pname) )
   256     {
   256 		{
   257       return 'DNE';
   257 			return 'DNE';
   258     }
   258 		}
   259     
   259 		
   260     if ( isPage($pname) )
   260 		if ( isPage($pname) )
   261     {
   261 		{
   262       $password_exists = ( !empty($cdata['password']) && $cdata['password'] !== sha1('') );
   262 			$password_exists = ( !empty($cdata['password']) && $cdata['password'] !== sha1('') );
   263       if ( $password_exists && $password !== $cdata['password'] )
   263 			if ( $password_exists && $password !== $cdata['password'] )
   264       {
   264 			{
   265         return '<p>' . $lang->get('history_err_wrong_password') . '</p>';
   265 				return '<p>' . $lang->get('history_err_wrong_password') . '</p>';
   266       }
   266 			}
   267     }
   267 		}
   268     
   268 		
   269     $wiki = ( ( $cdata['wiki_mode'] == 2 && getConfig('wiki_mode') == '1') || $cdata['wiki_mode'] == 1) ? true : false;
   269 		$wiki = ( ( $cdata['wiki_mode'] == 2 && getConfig('wiki_mode') == '1') || $cdata['wiki_mode'] == 1) ? true : false;
   270     $prot = ( ( $cdata['protected'] == 2 && $session->user_logged_in && $session->reg_time + 60*60*24*4 < time() ) || $cdata['protected'] == 1) ? true : false;
   270 		$prot = ( ( $cdata['protected'] == 2 && $session->user_logged_in && $session->reg_time + 60*60*24*4 < time() ) || $cdata['protected'] == 1) ? true : false;
   271     
   271 		
   272     $q = 'SELECT log_id,time_id,date_string,page_id,namespace,author,author_uid,u.username,edit_summary,minor_edit FROM ' . table_prefix . "logs AS l\n"
   272 		$q = 'SELECT log_id,time_id,date_string,page_id,namespace,author,author_uid,u.username,edit_summary,minor_edit FROM ' . table_prefix . "logs AS l\n"
   273        . "  LEFT JOIN " . table_prefix . "users AS u\n"
   273  			. "  LEFT JOIN " . table_prefix . "users AS u\n"
   274        . "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
   274  			. "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
   275        . "  WHERE log_type='page' AND action='edit' AND page_id='$page_id' AND namespace='$namespace' AND is_draft != 1 ORDER BY time_id DESC;";
   275  			. "  WHERE log_type='page' AND action='edit' AND page_id='$page_id' AND namespace='$namespace' AND is_draft != 1 ORDER BY time_id DESC;";
   276     
   276 		
   277     if ( !($q = $db->sql_query($q)) )
   277 		if ( !($q = $db->sql_query($q)) )
   278       $db->_die('The history data for the page "' . $paths->cpage['name'] . '" could not be selected.');
   278 			$db->_die('The history data for the page "' . $paths->cpage['name'] . '" could not be selected.');
   279     
   279 		
   280     echo $lang->get('history_page_subtitle') . '
   280 		echo $lang->get('history_page_subtitle') . '
   281           <h3>' . $lang->get('history_heading_edits') . '</h3>';
   281 					<h3>' . $lang->get('history_heading_edits') . '</h3>';
   282     $numrows = $db->numrows();
   282 		$numrows = $db->numrows();
   283     if ( $numrows < 1 )
   283 		if ( $numrows < 1 )
   284     {
   284 		{
   285       echo $lang->get('history_no_entries');
   285 			echo $lang->get('history_no_entries');
   286     }
   286 		}
   287     else
   287 		else
   288     {
   288 		{
   289       echo '<form action="'.makeUrlNS($namespace, $page_id, 'do=diff').'" onsubmit="ajaxHistDiff(); return false;" method="get">
   289 			echo '<form action="'.makeUrlNS($namespace, $page_id, 'do=diff').'" onsubmit="ajaxHistDiff(); return false;" method="get">
   290             <input type="submit" value="' . $lang->get('history_btn_compare') . '" />
   290 						<input type="submit" value="' . $lang->get('history_btn_compare') . '" />
   291             ' . ( urlSeparator == '&' ? '<input type="hidden" name="title" value="' . htmlspecialchars($paths->nslist[$namespace] . $page_id) . '" />' : '' ) . '
   291 						' . ( urlSeparator == '&' ? '<input type="hidden" name="title" value="' . htmlspecialchars($paths->nslist[$namespace] . $page_id) . '" />' : '' ) . '
   292             ' . ( $session->sid_super ? '<input type="hidden" name="auth"  value="' . $session->sid_super . '" />' : '') . '
   292 						' . ( $session->sid_super ? '<input type="hidden" name="auth"  value="' . $session->sid_super . '" />' : '') . '
   293             <input type="hidden" name="do" value="diff" />
   293 						<input type="hidden" name="do" value="diff" />
   294             <br /><span>&nbsp;</span>
   294 						<br /><span>&nbsp;</span>
   295             <div class="tblholder">
   295 						<div class="tblholder">
   296             <table border="0" width="100%" cellspacing="1" cellpadding="4">
   296 						<table border="0" width="100%" cellspacing="1" cellpadding="4">
   297             <tr>
   297 						<tr>
   298               <th colspan="2">' . $lang->get('history_col_diff') . '</th>
   298 							<th colspan="2">' . $lang->get('history_col_diff') . '</th>
   299               <th>' . $lang->get('history_col_datetime') . '</th>
   299 							<th>' . $lang->get('history_col_datetime') . '</th>
   300               <th>' . $lang->get('history_col_user') . '</th>
   300 							<th>' . $lang->get('history_col_user') . '</th>
   301               <th>' . $lang->get('history_col_summary') . '</th>
   301 							<th>' . $lang->get('history_col_summary') . '</th>
   302               <th>' . $lang->get('history_col_minor') . '</th>
   302 							<th>' . $lang->get('history_col_minor') . '</th>
   303               <th colspan="3">' . $lang->get('history_col_actions') . '</th>
   303 							<th colspan="3">' . $lang->get('history_col_actions') . '</th>
   304             </tr>'."\n"."\n";
   304 						</tr>'."\n"."\n";
   305       $cls = 'row2';
   305 			$cls = 'row2';
   306       $ticker = 0;
   306 			$ticker = 0;
   307       
   307 			
   308       while ( $r = $db->fetchrow($q) )
   308 			while ( $r = $db->fetchrow($q) )
   309       {
   309 			{
   310         
   310 				
   311         $ticker++;
   311 				$ticker++;
   312         
   312 				
   313         if($cls == 'row2') $cls = 'row1';
   313 				if($cls == 'row2') $cls = 'row1';
   314         else $cls = 'row2';
   314 				else $cls = 'row2';
   315         
   315 				
   316         echo '<tr>'."\n";
   316 				echo '<tr>'."\n";
   317         
   317 				
   318         // Diff selection
   318 				// Diff selection
   319         if($ticker == 1)
   319 				if($ticker == 1)
   320         {
   320 				{
   321           $s1 = '';
   321 					$s1 = '';
   322           $s2 = 'checked="checked" ';
   322 					$s2 = 'checked="checked" ';
   323         }
   323 				}
   324         elseif($ticker == 2)
   324 				elseif($ticker == 2)
   325         {
   325 				{
   326           $s1 = 'checked="checked" ';
   326 					$s1 = 'checked="checked" ';
   327           $s2 = '';
   327 					$s2 = '';
   328         }
   328 				}
   329         else
   329 				else
   330         {
   330 				{
   331           $s1 = '';
   331 					$s1 = '';
   332           $s2 = '';
   332 					$s2 = '';
   333         }
   333 				}
   334         if($ticker > 1)        echo '<td class="' . $cls . '" style="padding: 0;"><input ' . $s1 . 'name="diff1" type="radio" value="' . $r['time_id'] . '" id="diff1_' . $r['time_id'] . '" class="clsDiff1Radio" onclick="selectDiff1Button(this);" /></td>'."\n"; else echo '<td class="' . $cls . '"></td>';
   334 				if($ticker > 1)        echo '<td class="' . $cls . '" style="padding: 0;"><input ' . $s1 . 'name="diff1" type="radio" value="' . $r['time_id'] . '" id="diff1_' . $r['time_id'] . '" class="clsDiff1Radio" onclick="selectDiff1Button(this);" /></td>'."\n"; else echo '<td class="' . $cls . '"></td>';
   335         if($ticker < $numrows) echo '<td class="' . $cls . '" style="padding: 0;"><input ' . $s2 . 'name="diff2" type="radio" value="' . $r['time_id'] . '" id="diff2_' . $r['time_id'] . '" class="clsDiff2Radio" onclick="selectDiff2Button(this);" /></td>'."\n"; else echo '<td class="' . $cls . '"></td>';
   335 				if($ticker < $numrows) echo '<td class="' . $cls . '" style="padding: 0;"><input ' . $s2 . 'name="diff2" type="radio" value="' . $r['time_id'] . '" id="diff2_' . $r['time_id'] . '" class="clsDiff2Radio" onclick="selectDiff2Button(this);" /></td>'."\n"; else echo '<td class="' . $cls . '"></td>';
   336         
   336 				
   337         // Date and time
   337 				// Date and time
   338         echo '<td class="' . $cls . '" style="white-space: nowrap;">' . enano_date(ED_DATE | ED_TIME, intval($r['time_id'])) . '</td class="' . $cls . '">'."\n";
   338 				echo '<td class="' . $cls . '" style="white-space: nowrap;">' . enano_date(ED_DATE | ED_TIME, intval($r['time_id'])) . '</td class="' . $cls . '">'."\n";
   339         
   339 				
   340         // User
   340 				// User
   341         $real_username = $r['author_uid'] > 1 && !empty($r['username']) ? $r['username'] : $r['author'];
   341 				$real_username = $r['author_uid'] > 1 && !empty($r['username']) ? $r['username'] : $r['author'];
   342         $rank_info = $session->get_user_rank($r['author_uid']);
   342 				$rank_info = $session->get_user_rank($r['author_uid']);
   343         if ( $session->get_permissions('mod_misc') && is_valid_ip($r['author']) && $r['author_uid'] == 1 )
   343 				if ( $session->get_permissions('mod_misc') && is_valid_ip($r['author']) && $r['author_uid'] == 1 )
   344         {
   344 				{
   345           $rc = ' style="cursor: pointer;" title="' . $lang->get('history_tip_rdns') . '" onclick="ajaxReverseDNS(this, \'' . $r['author'] . '\');"';
   345 					$rc = ' style="cursor: pointer;" title="' . $lang->get('history_tip_rdns') . '" onclick="ajaxReverseDNS(this, \'' . $r['author'] . '\');"';
   346         }
   346 				}
   347         else
   347 				else
   348         {
   348 				{
   349           $rc = '';
   349 					$rc = '';
   350         }
   350 				}
   351         echo '<td class="' . $cls . '"' . $rc . '><a href="'.makeUrlNS('User', sanitize_page_id($real_username)).'" ';
   351 				echo '<td class="' . $cls . '"' . $rc . '><a href="'.makeUrlNS('User', sanitize_page_id($real_username)).'" ';
   352         if ( !isPage($paths->nslist['User'] . sanitize_page_id($real_username)) )
   352 				if ( !isPage($paths->nslist['User'] . sanitize_page_id($real_username)) )
   353         {
   353 				{
   354           echo 'class="wikilink-nonexistent"';
   354 					echo 'class="wikilink-nonexistent"';
   355         }
   355 				}
   356         echo 'style="' . $rank_info['rank_style'] . '">' . htmlspecialchars($real_username) . '</a></td class="' . $cls . '">'."\n";
   356 				echo 'style="' . $rank_info['rank_style'] . '">' . htmlspecialchars($real_username) . '</a></td class="' . $cls . '">'."\n";
   357         
   357 				
   358         // Edit summary
   358 				// Edit summary
   359         if ( $r['edit_summary'] == 'Automatic backup created when logs were purged' )
   359 				if ( $r['edit_summary'] == 'Automatic backup created when logs were purged' )
   360         {
   360 				{
   361           $r['edit_summary'] = $lang->get('history_summary_clearlogs');
   361 					$r['edit_summary'] = $lang->get('history_summary_clearlogs');
   362         }
   362 				}
   363         echo '<td class="' . $cls . '">' . $r['edit_summary'] . '</td>'."\n";
   363 				echo '<td class="' . $cls . '">' . $r['edit_summary'] . '</td>'."\n";
   364         
   364 				
   365         // Minor edit
   365 				// Minor edit
   366         echo '<td class="' . $cls . '" style="text-align: center;">'. (( $r['minor_edit'] ) ? 'M' : '' ) .'</td>'."\n";
   366 				echo '<td class="' . $cls . '" style="text-align: center;">'. (( $r['minor_edit'] ) ? 'M' : '' ) .'</td>'."\n";
   367         
   367 				
   368         // Actions!
   368 				// Actions!
   369         echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrlNS($namespace, $page_id, 'oldid=' . $r['log_id']) . '" onclick="ajaxHistView(\'' . $r['log_id'] . '\'); return false;">' . $lang->get('history_action_view') . '</a></td>'."\n";
   369 				echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrlNS($namespace, $page_id, 'oldid=' . $r['log_id']) . '" onclick="ajaxHistView(\'' . $r['log_id'] . '\'); return false;">' . $lang->get('history_action_view') . '</a></td>'."\n";
   370         echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrl($paths->nslist['Special'].'Contributions/' . $r['author']) . '">' . $lang->get('history_action_contrib') . '</a></td>'."\n";
   370 				echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrl($paths->nslist['Special'].'Contributions/' . $r['author']) . '">' . $lang->get('history_action_contrib') . '</a></td>'."\n";
   371         echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrlNS($namespace, $page_id, 'do=edit&amp;revid=' . $r['log_id']) . '" onclick="ajaxEditor(\'' . $r['log_id'] . '\'); return false;">' . $lang->get('history_action_restore') . '</a></td>'."\n";
   371 				echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrlNS($namespace, $page_id, 'do=edit&amp;revid=' . $r['log_id']) . '" onclick="ajaxEditor(\'' . $r['log_id'] . '\'); return false;">' . $lang->get('history_action_restore') . '</a></td>'."\n";
   372         
   372 				
   373         echo '</tr>'."\n"."\n";
   373 				echo '</tr>'."\n"."\n";
   374         
   374 				
   375       }
   375 			}
   376       echo '</table>
   376 			echo '</table>
   377             </div>
   377 						</div>
   378             <br />
   378 						<br />
   379             <input type="hidden" name="do" value="diff" />
   379 						<input type="hidden" name="do" value="diff" />
   380             <input type="submit" value="' . $lang->get('history_btn_compare') . '" />
   380 						<input type="submit" value="' . $lang->get('history_btn_compare') . '" />
   381             </form>
   381 						</form>
   382             <script type="text/javascript">if ( !KILL_SWITCH ) { buildDiffList(); }</script>';
   382 						<script type="text/javascript">if ( !KILL_SWITCH ) { buildDiffList(); }</script>';
   383     }
   383 		}
   384     $db->free_result();
   384 		$db->free_result();
   385     echo '<h3>' . $lang->get('history_heading_other') . '</h3>';
   385 		echo '<h3>' . $lang->get('history_heading_other') . '</h3>';
   386     
   386 		
   387     $sql = 'SELECT log_id,action,time_id,date_string,page_id,namespace,author,author_uid,u.username,edit_summary,minor_edit FROM ' . table_prefix . "logs AS l\n"
   387 		$sql = 'SELECT log_id,action,time_id,date_string,page_id,namespace,author,author_uid,u.username,edit_summary,minor_edit FROM ' . table_prefix . "logs AS l\n"
   388          . "  LEFT JOIN " . table_prefix . "users AS u\n"
   388  				. "  LEFT JOIN " . table_prefix . "users AS u\n"
   389          . "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
   389  				. "    ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n"
   390          . "  WHERE log_type='page' AND action!='edit' AND page_id='$page_id' AND namespace='$namespace' AND is_draft != 1 ORDER BY time_id DESC;";
   390  				. "  WHERE log_type='page' AND action!='edit' AND page_id='$page_id' AND namespace='$namespace' AND is_draft != 1 ORDER BY time_id DESC;";
   391     
   391 		
   392     if ( !( $q = $db->sql_query($sql)) )
   392 		if ( !( $q = $db->sql_query($sql)) )
   393     {
   393 		{
   394       $db->_die('The history data for the page "' . htmlspecialchars($paths->cpage['name']) . '" could not be selected.');
   394 			$db->_die('The history data for the page "' . htmlspecialchars($paths->cpage['name']) . '" could not be selected.');
   395     }
   395 		}
   396     if ( $db->numrows() < 1 )
   396 		if ( $db->numrows() < 1 )
   397     {
   397 		{
   398       echo $lang->get('history_no_entries');
   398 			echo $lang->get('history_no_entries');
   399     }
   399 		}
   400     else
   400 		else
   401     {
   401 		{
   402       
   402 			
   403       echo '<div class="tblholder">
   403 			echo '<div class="tblholder">
   404               <table border="0" width="100%" cellspacing="1" cellpadding="4"><tr>
   404 							<table border="0" width="100%" cellspacing="1" cellpadding="4"><tr>
   405                 <th>' . $lang->get('history_col_datetime') . '</th>
   405 								<th>' . $lang->get('history_col_datetime') . '</th>
   406                 <th>' . $lang->get('history_col_user') . '</th>
   406 								<th>' . $lang->get('history_col_user') . '</th>
   407                 <th>' . $lang->get('history_col_minor') . '</th>
   407 								<th>' . $lang->get('history_col_minor') . '</th>
   408                 <th>' . $lang->get('history_col_action_taken') . '</th>
   408 								<th>' . $lang->get('history_col_action_taken') . '</th>
   409                 <th>' . $lang->get('history_col_extra') . '</th>
   409 								<th>' . $lang->get('history_col_extra') . '</th>
   410                 <th colspan="2"></th>
   410 								<th colspan="2"></th>
   411               </tr>';
   411 							</tr>';
   412       $cls = 'row2';
   412 			$cls = 'row2';
   413       while($r = $db->fetchrow($q)) {
   413 			while($r = $db->fetchrow($q)) {
   414         
   414 				
   415         if($cls == 'row2') $cls = 'row1';
   415 				if($cls == 'row2') $cls = 'row1';
   416         else $cls = 'row2';
   416 				else $cls = 'row2';
   417         
   417 				
   418         echo '<tr>';
   418 				echo '<tr>';
   419         
   419 				
   420         // Date and time
   420 				// Date and time
   421         echo '<td class="' . $cls . '">' . enano_date(ED_DATE | ED_TIME, intval($r['time_id'])) . '</td class="' . $cls . '">';
   421 				echo '<td class="' . $cls . '">' . enano_date(ED_DATE | ED_TIME, intval($r['time_id'])) . '</td class="' . $cls . '">';
   422         
   422 				
   423         // User
   423 				// User
   424         $real_username = $r['author_uid'] > 1 && !empty($r['username']) ? $r['username'] : $r['author'];
   424 				$real_username = $r['author_uid'] > 1 && !empty($r['username']) ? $r['username'] : $r['author'];
   425         $rank_info = $session->get_user_rank($r['author_uid']);
   425 				$rank_info = $session->get_user_rank($r['author_uid']);
   426         if ( $session->get_permissions('mod_misc') && is_valid_ip($r['author']) && $r['author_uid'] == 1 )
   426 				if ( $session->get_permissions('mod_misc') && is_valid_ip($r['author']) && $r['author_uid'] == 1 )
   427         {
   427 				{
   428           $rc = ' style="cursor: pointer;" title="' . $lang->get('history_tip_rdns') . '" onclick="ajaxReverseDNS(this, \'' . $r['author'] . '\');"';
   428 					$rc = ' style="cursor: pointer;" title="' . $lang->get('history_tip_rdns') . '" onclick="ajaxReverseDNS(this, \'' . $r['author'] . '\');"';
   429         }
   429 				}
   430         else
   430 				else
   431         {
   431 				{
   432           $rc = '';
   432 					$rc = '';
   433         }
   433 				}
   434         echo '<td class="' . $cls . '"' . $rc . '><a href="'.makeUrlNS('User', sanitize_page_id($real_username)).'" ';
   434 				echo '<td class="' . $cls . '"' . $rc . '><a href="'.makeUrlNS('User', sanitize_page_id($real_username)).'" ';
   435         if ( !isPage($paths->nslist['User'] . sanitize_page_id($real_username)) )
   435 				if ( !isPage($paths->nslist['User'] . sanitize_page_id($real_username)) )
   436         {
   436 				{
   437           echo 'class="wikilink-nonexistent"';
   437 					echo 'class="wikilink-nonexistent"';
   438         }
   438 				}
   439         echo 'style="' . $rank_info['rank_style'] . '">' . htmlspecialchars($real_username) . '</a></td class="' . $cls . '">'."\n";
   439 				echo 'style="' . $rank_info['rank_style'] . '">' . htmlspecialchars($real_username) . '</a></td class="' . $cls . '">'."\n";
   440         
   440 				
   441         
   441 				
   442         // Minor edit
   442 				// Minor edit
   443         echo '<td class="' . $cls . '" style="text-align: center;">'. (( $r['minor_edit'] ) ? 'M' : '' ) .'</td>';
   443 				echo '<td class="' . $cls . '" style="text-align: center;">'. (( $r['minor_edit'] ) ? 'M' : '' ) .'</td>';
   444         
   444 				
   445         // Action taken
   445 				// Action taken
   446         echo '<td class="' . $cls . '">';
   446 				echo '<td class="' . $cls . '">';
   447         // Some of these are sanitized at insert-time. Others follow the newer Enano policy of stripping HTML at runtime.
   447 				// Some of these are sanitized at insert-time. Others follow the newer Enano policy of stripping HTML at runtime.
   448         if    ($r['action']=='prot')     echo $lang->get('history_log_protect') . '</td><td class="' . $cls . '">'     . $lang->get('history_extra_reason') . ' ' . ( $r['edit_summary'] === '__REVERSION__' ? $lang->get('history_extra_protection_reversion') : htmlspecialchars($r['edit_summary']) );
   448 				if    ($r['action']=='prot')     echo $lang->get('history_log_protect') . '</td><td class="' . $cls . '">'     . $lang->get('history_extra_reason') . ' ' . ( $r['edit_summary'] === '__REVERSION__' ? $lang->get('history_extra_protection_reversion') : htmlspecialchars($r['edit_summary']) );
   449         elseif($r['action']=='unprot')   echo $lang->get('history_log_unprotect') . '</td><td class="' . $cls . '">'   . $lang->get('history_extra_reason') . ' ' . ( $r['edit_summary'] === '__REVERSION__' ? $lang->get('history_extra_protection_reversion') : htmlspecialchars($r['edit_summary']) );
   449 				elseif($r['action']=='unprot')   echo $lang->get('history_log_unprotect') . '</td><td class="' . $cls . '">'   . $lang->get('history_extra_reason') . ' ' . ( $r['edit_summary'] === '__REVERSION__' ? $lang->get('history_extra_protection_reversion') : htmlspecialchars($r['edit_summary']) );
   450         elseif($r['action']=='semiprot') echo $lang->get('history_log_semiprotect') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . ( $r['edit_summary'] === '__REVERSION__' ? $lang->get('history_extra_protection_reversion') : htmlspecialchars($r['edit_summary']) );
   450 				elseif($r['action']=='semiprot') echo $lang->get('history_log_semiprotect') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . ( $r['edit_summary'] === '__REVERSION__' ? $lang->get('history_extra_protection_reversion') : htmlspecialchars($r['edit_summary']) );
   451         elseif($r['action']=='rename')   echo $lang->get('history_log_rename') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_oldtitle') . ' '.htmlspecialchars($r['edit_summary']);
   451 				elseif($r['action']=='rename')   echo $lang->get('history_log_rename') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_oldtitle') . ' '.htmlspecialchars($r['edit_summary']);
   452         elseif($r['action']=='create')   echo $lang->get('history_log_create') . '</td><td class="' . $cls . '">';
   452 				elseif($r['action']=='create')   echo $lang->get('history_log_create') . '</td><td class="' . $cls . '">';
   453         elseif($r['action']=='delete')   echo $lang->get('history_log_delete') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $r['edit_summary'];
   453 				elseif($r['action']=='delete')   echo $lang->get('history_log_delete') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $r['edit_summary'];
   454         elseif($r['action']=='reupload') echo $lang->get('history_log_uploadnew') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . ( $r['edit_summary'] === '__ROLLBACK__' ? $lang->get('history_extra_upload_reversion') : htmlspecialchars($r['edit_summary']) );
   454 				elseif($r['action']=='reupload') echo $lang->get('history_log_uploadnew') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . ( $r['edit_summary'] === '__ROLLBACK__' ? $lang->get('history_extra_upload_reversion') : htmlspecialchars($r['edit_summary']) );
   455         elseif($r['action']=='votereset')echo $lang->get('history_log_votereset') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_numvotes') . ' ' . $r['edit_summary'];
   455 				elseif($r['action']=='votereset')echo $lang->get('history_log_votereset') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_numvotes') . ' ' . $r['edit_summary'];
   456         echo '</td>';
   456 				echo '</td>';
   457         
   457 				
   458         // Actions!
   458 				// Actions!
   459         echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrl($paths->nslist['Special'].'Contributions/' . $r['author']) . '">' . $lang->get('history_action_contrib') . '</a></td>';
   459 				echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrl($paths->nslist['Special'].'Contributions/' . $r['author']) . '">' . $lang->get('history_action_contrib') . '</a></td>';
   460         echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrlNS($namespace, $page_id, 'do=rollback&amp;id=' . $r['log_id']) . '" onclick="ajaxRollback(\'' . $r['log_id'] . '\'); return false;">' . $lang->get('history_action_revert') . '</a></td>';
   460 				echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrlNS($namespace, $page_id, 'do=rollback&amp;id=' . $r['log_id']) . '" onclick="ajaxRollback(\'' . $r['log_id'] . '\'); return false;">' . $lang->get('history_action_revert') . '</a></td>';
   461         
   461 				
   462         echo '</tr>';
   462 				echo '</tr>';
   463       }
   463 			}
   464       echo '</table></div>';
   464 			echo '</table></div>';
   465     }
   465 		}
   466     $db->free_result();
   466 		$db->free_result();
   467     $ret = ob_get_contents();
   467 		$ret = ob_get_contents();
   468     ob_end_clean();
   468 		ob_end_clean();
   469     return $ret;
   469 		return $ret;
   470   }
   470 	}
   471   
   471 	
   472   /**
   472 	/**
   473    * Rolls back a logged action
   473  	* Rolls back a logged action
   474    * @param $id the time ID, a.k.a. the primary key in the logs table
   474  	* @param $id the time ID, a.k.a. the primary key in the logs table
   475    * @return string
   475  	* @return string
   476    */
   476  	*/
   477    
   477  	
   478   public static function rollback($id)
   478 	public static function rollback($id)
   479   {
   479 	{
   480     global $db, $session, $paths, $template, $plugins; // Common objects
   480 		global $db, $session, $paths, $template, $plugins; // Common objects
   481     global $lang;
   481 		global $lang;
   482     
   482 		
   483     // placeholder
   483 		// placeholder
   484     return 'PageUtils->rollback() is deprecated - use PageProcessor instead.';
   484 		return 'PageUtils->rollback() is deprecated - use PageProcessor instead.';
   485   }
   485 	}
   486   
   486 	
   487   /**
   487 	/**
   488    * Posts a comment.
   488  	* Posts a comment.
   489    * @param $page_id the page ID
   489  	* @param $page_id the page ID
   490    * @param $namespace the namespace
   490  	* @param $namespace the namespace
   491    * @param $name the name of the person posting, defaults to current username/IP
   491  	* @param $name the name of the person posting, defaults to current username/IP
   492    * @param $subject the subject line of the comment
   492  	* @param $subject the subject line of the comment
   493    * @param $text the comment text
   493  	* @param $text the comment text
   494    * @return string javascript code
   494  	* @return string javascript code
   495    */
   495  	*/
   496    
   496  	
   497   public static function addcomment($page_id, $namespace, $name, $subject, $text, $captcha_code = false, $captcha_id = false)
   497 	public static function addcomment($page_id, $namespace, $name, $subject, $text, $captcha_code = false, $captcha_id = false)
   498   {
   498 	{
   499     global $db, $session, $paths, $template, $plugins; // Common objects
   499 		global $db, $session, $paths, $template, $plugins; // Common objects
   500     $_ob = '';
   500 		$_ob = '';
   501     if(!$session->get_permissions('post_comments'))
   501 		if(!$session->get_permissions('post_comments'))
   502       return 'Access denied';
   502 			return 'Access denied';
   503     if(getConfig('comments_need_login') == '2' && !$session->user_logged_in) _die('Access denied to post comments: you need to be logged in first.');
   503 		if(getConfig('comments_need_login') == '2' && !$session->user_logged_in) _die('Access denied to post comments: you need to be logged in first.');
   504     if(getConfig('comments_need_login') == '1' && !$session->user_logged_in)
   504 		if(getConfig('comments_need_login') == '1' && !$session->user_logged_in)
   505     {
   505 		{
   506       if(!$captcha_code || !$captcha_id) _die('BUG: PageUtils::addcomment: no CAPTCHA data passed to method');
   506 			if(!$captcha_code || !$captcha_id) _die('BUG: PageUtils::addcomment: no CAPTCHA data passed to method');
   507       $result = $session->get_captcha($captcha_id);
   507 			$result = $session->get_captcha($captcha_id);
   508       if(strtolower($captcha_code) != strtolower($result)) _die('The confirmation code you entered was incorrect.');
   508 			if(strtolower($captcha_code) != strtolower($result)) _die('The confirmation code you entered was incorrect.');
   509     }
   509 		}
   510     $text = RenderMan::preprocess_text($text);
   510 		$text = RenderMan::preprocess_text($text);
   511     $name = $session->user_logged_in ? RenderMan::preprocess_text($session->username) : RenderMan::preprocess_text($name);
   511 		$name = $session->user_logged_in ? RenderMan::preprocess_text($session->username) : RenderMan::preprocess_text($name);
   512     $subj = RenderMan::preprocess_text($subject);
   512 		$subj = RenderMan::preprocess_text($subject);
   513     if(getConfig('approve_comments', '0')=='1') $appr = '0'; else $appr = '1';
   513 		if(getConfig('approve_comments', '0')=='1') $appr = '0'; else $appr = '1';
   514     $q = 'INSERT INTO ' . table_prefix.'comments(page_id,namespace,subject,comment_data,name,user_id,approved,time) VALUES(\'' . $page_id . '\',\'' . $namespace . '\',\'' . $subj . '\',\'' . $text . '\',\'' . $name . '\',' . $session->user_id . ',' . $appr . ','.time().')';
   514 		$q = 'INSERT INTO ' . table_prefix.'comments(page_id,namespace,subject,comment_data,name,user_id,approved,time) VALUES(\'' . $page_id . '\',\'' . $namespace . '\',\'' . $subj . '\',\'' . $text . '\',\'' . $name . '\',' . $session->user_id . ',' . $appr . ','.time().')';
   515     $e = $db->sql_query($q);
   515 		$e = $db->sql_query($q);
   516     if(!$e) die('alert(unescape(\''.rawurlencode('Error inserting comment data: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'))');
   516 		if(!$e) die('alert(unescape(\''.rawurlencode('Error inserting comment data: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'))');
   517     else $_ob .= '<div class="info-box">Your comment has been posted.</div>';
   517 		else $_ob .= '<div class="info-box">Your comment has been posted.</div>';
   518     return PageUtils::comments($page_id, $namespace, false, Array(), $_ob);
   518 		return PageUtils::comments($page_id, $namespace, false, Array(), $_ob);
   519   }
   519 	}
   520   
   520 	
   521   /**
   521 	/**
   522    * Generates partly-compiled HTML/Javascript code to be eval'ed by the user's browser to display comments
   522  	* Generates partly-compiled HTML/Javascript code to be eval'ed by the user's browser to display comments
   523    * @param $page_id the page ID
   523  	* @param $page_id the page ID
   524    * @param $namespace the namespace
   524  	* @param $namespace the namespace
   525    * @param $action administrative action to perform, default is false
   525  	* @param $action administrative action to perform, default is false
   526    * @param $flags additional info for $action, shouldn't be used except when deleting/approving comments, etc.
   526  	* @param $flags additional info for $action, shouldn't be used except when deleting/approving comments, etc.
   527    * @param $_ob text to prepend to output, used by PageUtils::addcomment
   527  	* @param $_ob text to prepend to output, used by PageUtils::addcomment
   528    * @return array
   528  	* @return array
   529    * @access private
   529  	* @access private
   530    */
   530  	*/
   531    
   531  	
   532   public static function comments_raw($page_id, $namespace, $action = false, $flags = Array(), $_ob = '')
   532 	public static function comments_raw($page_id, $namespace, $action = false, $flags = Array(), $_ob = '')
   533   {
   533 	{
   534     global $db, $session, $paths, $template, $plugins; // Common objects
   534 		global $db, $session, $paths, $template, $plugins; // Common objects
   535     global $lang;
   535 		global $lang;
   536     
   536 		
   537     $pname = $paths->nslist[$namespace] . $page_id;
   537 		$pname = $paths->nslist[$namespace] . $page_id;
   538     $template->init_vars();
   538 		$template->init_vars();
   539     
   539 		
   540     ob_start();
   540 		ob_start();
   541     
   541 		
   542     if($action && $session->get_permissions('mod_comments')) // Nip hacking attempts in the bud
   542 		if($action && $session->get_permissions('mod_comments')) // Nip hacking attempts in the bud
   543     {
   543 		{
   544       switch($action) {
   544 			switch($action) {
   545       case "delete":
   545 			case "delete":
   546         if(isset($flags['id']))
   546 				if(isset($flags['id']))
   547         {
   547 				{
   548           $q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND comment_id='.intval($flags['id']).' LIMIT 1;';
   548 					$q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND comment_id='.intval($flags['id']).' LIMIT 1;';
   549         } else {
   549 				} else {
   550           $n = $db->escape($flags['name']);
   550 					$n = $db->escape($flags['name']);
   551           $s = $db->escape($flags['subj']);
   551 					$s = $db->escape($flags['subj']);
   552           $t = $db->escape($flags['text']);
   552 					$t = $db->escape($flags['text']);
   553           $q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND name=\'' . $n . '\' AND subject=\'' . $s . '\' AND comment_data=\'' . $t . '\' LIMIT 1;';
   553 					$q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND name=\'' . $n . '\' AND subject=\'' . $s . '\' AND comment_data=\'' . $t . '\' LIMIT 1;';
   554         }
   554 				}
   555         $e=$db->sql_query($q);
   555 				$e=$db->sql_query($q);
   556         if(!$e) die('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   556 				if(!$e) die('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   557         break;
   557 				break;
   558       case "approve":
   558 			case "approve":
   559         if(isset($flags['id']))
   559 				if(isset($flags['id']))
   560         {
   560 				{
   561           $where = 'comment_id='.intval($flags['id']);
   561 					$where = 'comment_id='.intval($flags['id']);
   562         } else {
   562 				} else {
   563           $n = $db->escape($flags['name']);
   563 					$n = $db->escape($flags['name']);
   564           $s = $db->escape($flags['subj']);
   564 					$s = $db->escape($flags['subj']);
   565           $t = $db->escape($flags['text']);
   565 					$t = $db->escape($flags['text']);
   566           $where = 'name=\'' . $n . '\' AND subject=\'' . $s . '\' AND comment_data=\'' . $t . '\'';
   566 					$where = 'name=\'' . $n . '\' AND subject=\'' . $s . '\' AND comment_data=\'' . $t . '\'';
   567         }
   567 				}
   568         $q = 'SELECT approved FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND ' . $where . ' LIMIT 1;';
   568 				$q = 'SELECT approved FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND ' . $where . ' LIMIT 1;';
   569         $e = $db->sql_query($q);
   569 				$e = $db->sql_query($q);
   570         if(!$e) die('alert(unesape(\''.rawurlencode('Error selecting approval status: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   570 				if(!$e) die('alert(unesape(\''.rawurlencode('Error selecting approval status: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   571         $r = $db->fetchrow();
   571 				$r = $db->fetchrow();
   572         $db->free_result();
   572 				$db->free_result();
   573         $a = ( $r['approved'] ) ? '0' : '1';
   573 				$a = ( $r['approved'] ) ? '0' : '1';
   574         $q = 'UPDATE ' . table_prefix.'comments SET approved=' . $a . ' WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND ' . $where . ';';
   574 				$q = 'UPDATE ' . table_prefix.'comments SET approved=' . $a . ' WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND ' . $where . ';';
   575         $e=$db->sql_query($q);
   575 				$e=$db->sql_query($q);
   576         if(!$e) die('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   576 				if(!$e) die('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   577         if($a=='1') $v = $lang->get('comment_btn_mod_unapprove');
   577 				if($a=='1') $v = $lang->get('comment_btn_mod_unapprove');
   578         else $v = $lang->get('comment_btn_mod_approve');
   578 				else $v = $lang->get('comment_btn_mod_approve');
   579         echo 'document.getElementById("mdgApproveLink'.intval($_GET['id']).'").innerHTML="' . $v . '";';
   579 				echo 'document.getElementById("mdgApproveLink'.intval($_GET['id']).'").innerHTML="' . $v . '";';
   580         break;
   580 				break;
   581       }
   581 			}
   582     }
   582 		}
   583     
   583 		
   584     if(!defined('ENANO_TEMPLATE_LOADED'))
   584 		if(!defined('ENANO_TEMPLATE_LOADED'))
   585     {
   585 		{
   586       $template->load_theme($session->theme, $session->style);
   586 			$template->load_theme($session->theme, $session->style);
   587     }
   587 		}
   588     
   588 		
   589     $tpl = $template->makeParser('comment.tpl');
   589 		$tpl = $template->makeParser('comment.tpl');
   590     
   590 		
   591     $e = $db->sql_query('SELECT * FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND approved=0;');
   591 		$e = $db->sql_query('SELECT * FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND approved=0;');
   592     if(!$e) $db->_die('The comment text data could not be selected.');
   592 		if(!$e) $db->_die('The comment text data could not be selected.');
   593     $num_unapp = $db->numrows();
   593 		$num_unapp = $db->numrows();
   594     $db->free_result();
   594 		$db->free_result();
   595     $e = $db->sql_query('SELECT * FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND approved=1;');
   595 		$e = $db->sql_query('SELECT * FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND approved=1;');
   596     if(!$e) $db->_die('The comment text data could not be selected.');
   596 		if(!$e) $db->_die('The comment text data could not be selected.');
   597     $num_app = $db->numrows();
   597 		$num_app = $db->numrows();
   598     $db->free_result();
   598 		$db->free_result();
   599     $lq = $db->sql_query('SELECT c.comment_id,c.subject,c.name,c.comment_data,c.approved,c.time,c.user_id,c.ip_address,u.user_level,u.email,u.signature,u.user_has_avatar,u.avatar_type
   599 		$lq = $db->sql_query('SELECT c.comment_id,c.subject,c.name,c.comment_data,c.approved,c.time,c.user_id,c.ip_address,u.user_level,u.email,u.signature,u.user_has_avatar,u.avatar_type
   600                   FROM ' . table_prefix.'comments AS c
   600 									FROM ' . table_prefix.'comments AS c
   601                   LEFT JOIN ' . table_prefix.'users AS u
   601 									LEFT JOIN ' . table_prefix.'users AS u
   602                     ON c.user_id=u.user_id
   602 										ON c.user_id=u.user_id
   603                   WHERE page_id=\'' . $page_id . '\'
   603 									WHERE page_id=\'' . $page_id . '\'
   604                   AND namespace=\'' . $namespace . '\' ORDER BY c.time ASC;');
   604 									AND namespace=\'' . $namespace . '\' ORDER BY c.time ASC;');
   605     if(!$lq) _die('The comment text data could not be selected. '.$db->get_error());
   605 		if(!$lq) _die('The comment text data could not be selected. '.$db->get_error());
   606     $_ob .= '<h3>' . $lang->get('comment_heading') . '</h3>';
   606 		$_ob .= '<h3>' . $lang->get('comment_heading') . '</h3>';
   607     
   607 		
   608     $n = ( $session->get_permissions('mod_comments')) ? $db->numrows() : $num_app;
   608 		$n = ( $session->get_permissions('mod_comments')) ? $db->numrows() : $num_app;
   609     
   609 		
   610     $subst = array(
   610 		$subst = array(
   611         'num_comments' => $n,
   611 				'num_comments' => $n,
   612         'page_type' => $template->namespace_string
   612 				'page_type' => $template->namespace_string
   613       );
   613 			);
   614     
   614 		
   615     $_ob .= '<p>';
   615 		$_ob .= '<p>';
   616     $_ob .= ( $n == 0 ) ? $lang->get('comment_msg_count_zero', $subst) : ( $n == 1 ? $lang->get('comment_msg_count_one', $subst) : $lang->get('comment_msg_count_plural', $subst) );
   616 		$_ob .= ( $n == 0 ) ? $lang->get('comment_msg_count_zero', $subst) : ( $n == 1 ? $lang->get('comment_msg_count_one', $subst) : $lang->get('comment_msg_count_plural', $subst) );
   617     
   617 		
   618     if ( $session->get_permissions('mod_comments') && $num_unapp > 0 )
   618 		if ( $session->get_permissions('mod_comments') && $num_unapp > 0 )
   619     {
   619 		{
   620       $_ob .= ' <span style="color: #D84308">' . $lang->get('comment_msg_count_unapp_mod', array( 'num_unapp' => $num_unapp )) . '</span>';
   620 			$_ob .= ' <span style="color: #D84308">' . $lang->get('comment_msg_count_unapp_mod', array( 'num_unapp' => $num_unapp )) . '</span>';
   621     }
   621 		}
   622     else if ( !$session->get_permissions('mod_comments') && $num_unapp > 0 )
   622 		else if ( !$session->get_permissions('mod_comments') && $num_unapp > 0 )
   623     {
   623 		{
   624       $ls = ( $num_unapp == 1 ) ? 'comment_msg_count_unapp_one' : 'comment_msg_count_unapp_plural';
   624 			$ls = ( $num_unapp == 1 ) ? 'comment_msg_count_unapp_one' : 'comment_msg_count_unapp_plural';
   625       $_ob .= ' <span>' . $lang->get($ls, array( 'num_unapp' => $num_unapp )) . '</span>';
   625 			$_ob .= ' <span>' . $lang->get($ls, array( 'num_unapp' => $num_unapp )) . '</span>';
   626     }
   626 		}
   627     $_ob .= '</p>';
   627 		$_ob .= '</p>';
   628     $list = 'list = { ';
   628 		$list = 'list = { ';
   629     // _die(htmlspecialchars($ttext));
   629 		// _die(htmlspecialchars($ttext));
   630     $i = -1;
   630 		$i = -1;
   631     while ( $row = $db->fetchrow($lq) )
   631 		while ( $row = $db->fetchrow($lq) )
   632     {
   632 		{
   633       $i++;
   633 			$i++;
   634       $strings = Array();
   634 			$strings = Array();
   635       $bool = Array();
   635 			$bool = Array();
   636       if ( $session->get_permissions('mod_comments') || $row['approved'] == COMMENT_APPROVED )
   636 			if ( $session->get_permissions('mod_comments') || $row['approved'] == COMMENT_APPROVED )
   637       {
   637 			{
   638         $list .= $i . ' : { \'comment\' : unescape(\''.rawurlencode($row['comment_data']).'\'), \'name\' : unescape(\''.rawurlencode($row['name']).'\'), \'subject\' : unescape(\''.rawurlencode($row['subject']).'\'), }, ';
   638 				$list .= $i . ' : { \'comment\' : unescape(\''.rawurlencode($row['comment_data']).'\'), \'name\' : unescape(\''.rawurlencode($row['name']).'\'), \'subject\' : unescape(\''.rawurlencode($row['subject']).'\'), }, ';
   639         
   639 				
   640         // Comment ID (used in the Javascript apps)
   640 				// Comment ID (used in the Javascript apps)
   641         $strings['ID'] = (string)$i;
   641 				$strings['ID'] = (string)$i;
   642         
   642 				
   643         // Determine the name, and whether to link to the user page or not
   643 				// Determine the name, and whether to link to the user page or not
   644         $name = '';
   644 				$name = '';
   645         if($row['user_id'] > 1) $name .= '<a href="'.makeUrlNS('User', sanitize_page_id(' ', '_', $row['name'])).'">';
   645 				if($row['user_id'] > 1) $name .= '<a href="'.makeUrlNS('User', sanitize_page_id(' ', '_', $row['name'])).'">';
   646         $name .= $row['name'];
   646 				$name .= $row['name'];
   647         if($row['user_id'] > 1) $name .= '</a>';
   647 				if($row['user_id'] > 1) $name .= '</a>';
   648         $strings['NAME'] = $name; unset($name);
   648 				$strings['NAME'] = $name; unset($name);
   649         
   649 				
   650         // Subject
   650 				// Subject
   651         $s = $row['subject'];
   651 				$s = $row['subject'];
   652         if(!$row['approved']) $s .= ' <span style="color: #D84308">' . $lang->get('comment_msg_note_unapp') . '</span>';
   652 				if(!$row['approved']) $s .= ' <span style="color: #D84308">' . $lang->get('comment_msg_note_unapp') . '</span>';
   653         $strings['SUBJECT'] = $s;
   653 				$strings['SUBJECT'] = $s;
   654         
   654 				
   655         // Date and time
   655 				// Date and time
   656         $strings['DATETIME'] = enano_date(ED_DATE | ED_TIME, $row['time']);
   656 				$strings['DATETIME'] = enano_date(ED_DATE | ED_TIME, $row['time']);
   657         
   657 				
   658         // User level
   658 				// User level
   659         switch($row['user_level'])
   659 				switch($row['user_level'])
   660         {
   660 				{
   661           default:
   661 					default:
   662           case USER_LEVEL_GUEST:
   662 					case USER_LEVEL_GUEST:
   663             $l = $lang->get('user_type_guest');
   663 						$l = $lang->get('user_type_guest');
   664             break;
   664 						break;
   665           case USER_LEVEL_MEMBER:
   665 					case USER_LEVEL_MEMBER:
   666           case USER_LEVEL_CHPREF:
   666 					case USER_LEVEL_CHPREF:
   667             $l = $lang->get('user_type_member');
   667 						$l = $lang->get('user_type_member');
   668             break;
   668 						break;
   669           case USER_LEVEL_MOD:
   669 					case USER_LEVEL_MOD:
   670             $l = $lang->get('user_type_mod');
   670 						$l = $lang->get('user_type_mod');
   671             break;
   671 						break;
   672           case USER_LEVEL_ADMIN:
   672 					case USER_LEVEL_ADMIN:
   673             $l = $lang->get('user_type_admin');
   673 						$l = $lang->get('user_type_admin');
   674             break;
   674 						break;
   675         }
   675 				}
   676         $strings['USER_LEVEL'] = $l; unset($l);
   676 				$strings['USER_LEVEL'] = $l; unset($l);
   677         
   677 				
   678         // The actual comment data
   678 				// The actual comment data
   679         $strings['DATA'] = RenderMan::render($row['comment_data']);
   679 				$strings['DATA'] = RenderMan::render($row['comment_data']);
   680         
   680 				
   681         if($session->get_permissions('edit_comments'))
   681 				if($session->get_permissions('edit_comments'))
   682         {
   682 				{
   683           // Edit link
   683 					// Edit link
   684           $strings['EDIT_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=editcomment&amp;id=' . $row['comment_id']) . '" id="editbtn_' . $i . '">' . $lang->get('comment_btn_edit') . '</a>';
   684 					$strings['EDIT_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=editcomment&amp;id=' . $row['comment_id']) . '" id="editbtn_' . $i . '">' . $lang->get('comment_btn_edit') . '</a>';
   685         
   685 				
   686           // Delete link
   686 					// Delete link
   687           $strings['DELETE_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=deletecomment&amp;id=' . $row['comment_id']) . '">' . $lang->get('comment_btn_delete') . '</a>';
   687 					$strings['DELETE_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=deletecomment&amp;id=' . $row['comment_id']) . '">' . $lang->get('comment_btn_delete') . '</a>';
   688         }
   688 				}
   689         else
   689 				else
   690         {
   690 				{
   691           // Edit link
   691 					// Edit link
   692           $strings['EDIT_LINK'] = '';
   692 					$strings['EDIT_LINK'] = '';
   693         
   693 				
   694           // Delete link
   694 					// Delete link
   695           $strings['DELETE_LINK'] = '';
   695 					$strings['DELETE_LINK'] = '';
   696         }
   696 				}
   697         
   697 				
   698         // Send PM link
   698 				// Send PM link
   699         $strings['SEND_PM_LINK'] = ( $session->user_logged_in && $row['user_id'] > 1 ) ? '<a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/To/' . $row['name']) . '">' . $lang->get('comment_btn_send_privmsg') . '</a><br />' : '';
   699 				$strings['SEND_PM_LINK'] = ( $session->user_logged_in && $row['user_id'] > 1 ) ? '<a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/To/' . $row['name']) . '">' . $lang->get('comment_btn_send_privmsg') . '</a><br />' : '';
   700         
   700 				
   701         // Add Buddy link
   701 				// Add Buddy link
   702         $strings['ADD_BUDDY_LINK'] = ( $session->user_logged_in && $row['user_id'] > 1 ) ? '<a href="'.makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' . $row['name']) . '">' . $lang->get('comment_btn_add_buddy') . '</a>' : '';
   702 				$strings['ADD_BUDDY_LINK'] = ( $session->user_logged_in && $row['user_id'] > 1 ) ? '<a href="'.makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' . $row['name']) . '">' . $lang->get('comment_btn_add_buddy') . '</a>' : '';
   703         
   703 				
   704         // Mod links
   704 				// Mod links
   705         $applink = '';
   705 				$applink = '';
   706         $applink .= '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=admin&amp;action=approve&amp;id=' . $row['comment_id']) . '" id="mdgApproveLink' . $i . '">';
   706 				$applink .= '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=admin&amp;action=approve&amp;id=' . $row['comment_id']) . '" id="mdgApproveLink' . $i . '">';
   707         if($row['approved']) $applink .= $lang->get('comment_btn_mod_unapprove');
   707 				if($row['approved']) $applink .= $lang->get('comment_btn_mod_unapprove');
   708         else $applink .= $lang->get('comment_btn_mod_approve');
   708 				else $applink .= $lang->get('comment_btn_mod_approve');
   709         $applink .= '</a>';
   709 				$applink .= '</a>';
   710         $strings['MOD_APPROVE_LINK'] = $applink; unset($applink);
   710 				$strings['MOD_APPROVE_LINK'] = $applink; unset($applink);
   711         $strings['MOD_DELETE_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=admin&amp;action=delete&amp;id=' . $row['comment_id']) . '">' . $lang->get('comment_btn_mod_delete') . '</a>';
   711 				$strings['MOD_DELETE_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=admin&amp;action=delete&amp;id=' . $row['comment_id']) . '">' . $lang->get('comment_btn_mod_delete') . '</a>';
   712         $strings['MOD_IP_LINK'] = '<span style="opacity: 0.5; filter: alpha(opacity=50);">' . ( ( empty($row['ip_address']) ) ? $lang->get('comment_btn_mod_ip_missing') : $lang->get('comment_btn_mod_ip_notimplemented') ) . '</span>';
   712 				$strings['MOD_IP_LINK'] = '<span style="opacity: 0.5; filter: alpha(opacity=50);">' . ( ( empty($row['ip_address']) ) ? $lang->get('comment_btn_mod_ip_missing') : $lang->get('comment_btn_mod_ip_notimplemented') ) . '</span>';
   713         
   713 				
   714         // Signature
   714 				// Signature
   715         $strings['SIGNATURE'] = '';
   715 				$strings['SIGNATURE'] = '';
   716         if($row['signature'] != '') $strings['SIGNATURE'] = RenderMan::render($row['signature']);
   716 				if($row['signature'] != '') $strings['SIGNATURE'] = RenderMan::render($row['signature']);
   717         
   717 				
   718         // Avatar
   718 				// Avatar
   719         if ( $row['user_has_avatar'] == 1 )
   719 				if ( $row['user_has_avatar'] == 1 )
   720         {
   720 				{
   721           $bool['user_has_avatar'] = true;
   721 					$bool['user_has_avatar'] = true;
   722           $strings['AVATAR_ALT'] = $lang->get('usercp_avatar_image_alt', array('username' => $row['name']));
   722 					$strings['AVATAR_ALT'] = $lang->get('usercp_avatar_image_alt', array('username' => $row['name']));
   723           $strings['AVATAR_URL'] = make_avatar_url(intval($row['user_id']), $row['avatar_type'], $row['email']);
   723 					$strings['AVATAR_URL'] = make_avatar_url(intval($row['user_id']), $row['avatar_type'], $row['email']);
   724           $strings['USERPAGE_LINK'] = makeUrlNS('User', $row['name']);
   724 					$strings['USERPAGE_LINK'] = makeUrlNS('User', $row['name']);
   725         }
   725 				}
   726         
   726 				
   727         $bool['auth_mod'] = ($session->get_permissions('mod_comments')) ? true : false;
   727 				$bool['auth_mod'] = ($session->get_permissions('mod_comments')) ? true : false;
   728         $bool['can_edit'] = ( ( $session->user_logged_in && $row['name'] == $session->username && $session->get_permissions('edit_comments') ) || $session->get_permissions('mod_comments') ) ? true : false;
   728 				$bool['can_edit'] = ( ( $session->user_logged_in && $row['name'] == $session->username && $session->get_permissions('edit_comments') ) || $session->get_permissions('mod_comments') ) ? true : false;
   729         $bool['signature'] = ( $strings['SIGNATURE'] == '' ) ? false : true;
   729 				$bool['signature'] = ( $strings['SIGNATURE'] == '' ) ? false : true;
   730         
   730 				
   731         // Done processing and compiling, now let's cook it into HTML
   731 				// Done processing and compiling, now let's cook it into HTML
   732         $tpl->assign_vars($strings);
   732 				$tpl->assign_vars($strings);
   733         $tpl->assign_bool($bool);
   733 				$tpl->assign_bool($bool);
   734         $_ob .= $tpl->run();
   734 				$_ob .= $tpl->run();
   735       }
   735 			}
   736     }
   736 		}
   737     if(getConfig('comments_need_login') != '2' || $session->user_logged_in)
   737 		if(getConfig('comments_need_login') != '2' || $session->user_logged_in)
   738     {
   738 		{
   739       if($session->get_permissions('post_comments'))
   739 			if($session->get_permissions('post_comments'))
   740       {
   740 			{
   741         $_ob .= '<h3>' . $lang->get('comment_postform_title') . '</h3>';
   741 				$_ob .= '<h3>' . $lang->get('comment_postform_title') . '</h3>';
   742         $_ob .= $lang->get('comment_postform_blurb');
   742 				$_ob .= $lang->get('comment_postform_blurb');
   743         if(getConfig('approve_comments', '0')=='1') $_ob .= ' ' . $lang->get('comment_postform_blurb_unapp');
   743 				if(getConfig('approve_comments', '0')=='1') $_ob .= ' ' . $lang->get('comment_postform_blurb_unapp');
   744         if(getConfig('comments_need_login') == '1' && !$session->user_logged_in)
   744 				if(getConfig('comments_need_login') == '1' && !$session->user_logged_in)
   745         {
   745 				{
   746           $_ob .= ' ' . $lang->get('comment_postform_blurb_captcha');
   746 					$_ob .= ' ' . $lang->get('comment_postform_blurb_captcha');
   747         }
   747 				}
   748         $sn = $session->user_logged_in ? $session->username . '<input name="name" id="mdgScreenName" type="hidden" value="' . $session->username . '" />' : '<input name="name" id="mdgScreenName" type="text" size="35" />';
   748 				$sn = $session->user_logged_in ? $session->username . '<input name="name" id="mdgScreenName" type="hidden" value="' . $session->username . '" />' : '<input name="name" id="mdgScreenName" type="text" size="35" />';
   749         $_ob .= '  <a href="#" id="mdgCommentFormLink" style="display: none;" onclick="document.getElementById(\'mdgCommentForm\').style.display=\'block\';this.style.display=\'none\';return false;">' . $lang->get('comment_postform_blurb_link') . '</a>
   749 				$_ob .= '  <a href="#" id="mdgCommentFormLink" style="display: none;" onclick="document.getElementById(\'mdgCommentForm\').style.display=\'block\';this.style.display=\'none\';return false;">' . $lang->get('comment_postform_blurb_link') . '</a>
   750         <div id="mdgCommentForm">
   750 				<div id="mdgCommentForm">
   751         <form action="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=postcomment').'" method="post" style="margin-left: 1em">
   751 				<form action="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=postcomment').'" method="post" style="margin-left: 1em">
   752         <table border="0">
   752 				<table border="0">
   753         <tr><td>' . $lang->get('comment_postform_field_name') . '</td><td>' . $sn . '</td></tr>
   753 				<tr><td>' . $lang->get('comment_postform_field_name') . '</td><td>' . $sn . '</td></tr>
   754         <tr><td>' . $lang->get('comment_postform_field_subject') . '</td><td><input name="subj" id="mdgSubject" type="text" size="35" /></td></tr>';
   754 				<tr><td>' . $lang->get('comment_postform_field_subject') . '</td><td><input name="subj" id="mdgSubject" type="text" size="35" /></td></tr>';
   755         if(getConfig('comments_need_login') == '1' && !$session->user_logged_in)
   755 				if(getConfig('comments_need_login') == '1' && !$session->user_logged_in)
   756         {
   756 				{
   757           $session->kill_captcha();
   757 					$session->kill_captcha();
   758           $captcha = $session->make_captcha();
   758 					$captcha = $session->make_captcha();
   759           $_ob .= '<tr><td>' . $lang->get('comment_postform_field_captcha_title') . '<br /><small>' . $lang->get('comment_postform_field_captcha_blurb') . '</small></td><td><img src="'.makeUrlNS('Special', 'Captcha/' . $captcha) . '" alt="Visual confirmation" style="cursor: pointer;" onclick="this.src = \''.makeUrlNS("Special", "Captcha/".$captcha).'/\'+Math.floor(Math.random() * 100000);" /><input name="captcha_id" id="mdgCaptchaID" type="hidden" value="' . $captcha . '" /><br />' . $lang->get('comment_postform_field_captcha_label') . ' <input name="captcha_input" id="mdgCaptchaInput" type="text" size="10" /><br /><small><script type="text/javascript">document.write("' . $lang->get('comment_postform_field_captcha_cantread_js') . '");</script><noscript>' . $lang->get('comment_postform_field_captcha_cantread_nojs') . '</noscript></small></td></tr>';
   759 					$_ob .= '<tr><td>' . $lang->get('comment_postform_field_captcha_title') . '<br /><small>' . $lang->get('comment_postform_field_captcha_blurb') . '</small></td><td><img src="'.makeUrlNS('Special', 'Captcha/' . $captcha) . '" alt="Visual confirmation" style="cursor: pointer;" onclick="this.src = \''.makeUrlNS("Special", "Captcha/".$captcha).'/\'+Math.floor(Math.random() * 100000);" /><input name="captcha_id" id="mdgCaptchaID" type="hidden" value="' . $captcha . '" /><br />' . $lang->get('comment_postform_field_captcha_label') . ' <input name="captcha_input" id="mdgCaptchaInput" type="text" size="10" /><br /><small><script type="text/javascript">document.write("' . $lang->get('comment_postform_field_captcha_cantread_js') . '");</script><noscript>' . $lang->get('comment_postform_field_captcha_cantread_nojs') . '</noscript></small></td></tr>';
   760         }
   760 				}
   761         $_ob .= '
   761 				$_ob .= '
   762         <tr><td valign="top">' . $lang->get('comment_postform_field_comment') . '</td><td><textarea name="text" id="mdgCommentArea" rows="10" cols="40"></textarea></td></tr>
   762 				<tr><td valign="top">' . $lang->get('comment_postform_field_comment') . '</td><td><textarea name="text" id="mdgCommentArea" rows="10" cols="40"></textarea></td></tr>
   763         <tr><td colspan="2" style="text-align: center;"><input type="submit" value="' . $lang->get('comment_postform_btn_submit') . '" /></td></tr>
   763 				<tr><td colspan="2" style="text-align: center;"><input type="submit" value="' . $lang->get('comment_postform_btn_submit') . '" /></td></tr>
   764         </table>
   764 				</table>
   765         </form>
   765 				</form>
   766         </div>';
   766 				</div>';
   767       }
   767 			}
   768     } else {
   768 		} else {
   769       // FIXME: l10n
   769 			// FIXME: l10n
   770       $_ob .= '<h3>' . $lang->get('comment_postform_title') . '</h3><p>You need to be logged in to post comments. <a href="'.makeUrlNS('Special', 'Login/' . $pname . '%2523comments').'">Log in</a></p>';
   770 			$_ob .= '<h3>' . $lang->get('comment_postform_title') . '</h3><p>You need to be logged in to post comments. <a href="'.makeUrlNS('Special', 'Login/' . $pname . '%2523comments').'">Log in</a></p>';
   771     }
   771 		}
   772     $list .= '};';
   772 		$list .= '};';
   773     echo 'document.getElementById(\'ajaxEditContainer\').innerHTML = unescape(\''. rawurlencode($_ob) .'\');
   773 		echo 'document.getElementById(\'ajaxEditContainer\').innerHTML = unescape(\''. rawurlencode($_ob) .'\');
   774     ' . $list;
   774 		' . $list;
   775     echo 'Fat.fade_all(); document.getElementById(\'mdgCommentForm\').style.display = \'none\'; document.getElementById(\'mdgCommentFormLink\').style.display="inline";';
   775 		echo 'Fat.fade_all(); document.getElementById(\'mdgCommentForm\').style.display = \'none\'; document.getElementById(\'mdgCommentFormLink\').style.display="inline";';
   776     
   776 		
   777     $ret = ob_get_contents();
   777 		$ret = ob_get_contents();
   778     ob_end_clean();
   778 		ob_end_clean();
   779     return Array($ret, $_ob);
   779 		return Array($ret, $_ob);
   780     
   780 		
   781   }
   781 	}
   782   
   782 	
   783   /**
   783 	/**
   784    * Generates ready-to-execute Javascript code to be eval'ed by the user's browser to display comments
   784  	* Generates ready-to-execute Javascript code to be eval'ed by the user's browser to display comments
   785    * @param $page_id the page ID
   785  	* @param $page_id the page ID
   786    * @param $namespace the namespace
   786  	* @param $namespace the namespace
   787    * @param $action administrative action to perform, default is false
   787  	* @param $action administrative action to perform, default is false
   788    * @param $flags additional info for $action, shouldn't be used except when deleting/approving comments, etc.
   788  	* @param $flags additional info for $action, shouldn't be used except when deleting/approving comments, etc.
   789    * @param $_ob text to prepend to output, used by PageUtils::addcomment
   789  	* @param $_ob text to prepend to output, used by PageUtils::addcomment
   790    * @return string
   790  	* @return string
   791    */
   791  	*/
   792    
   792  	
   793   public static function comments($page_id, $namespace, $action = false, $id = -1, $_ob = '')
   793 	public static function comments($page_id, $namespace, $action = false, $id = -1, $_ob = '')
   794   {
   794 	{
   795     global $db, $session, $paths, $template, $plugins; // Common objects
   795 		global $db, $session, $paths, $template, $plugins; // Common objects
   796     $r = PageUtils::comments_raw($page_id, $namespace, $action, $id, $_ob);
   796 		$r = PageUtils::comments_raw($page_id, $namespace, $action, $id, $_ob);
   797     return $r[0];
   797 		return $r[0];
   798   }
   798 	}
   799   
   799 	
   800   /**
   800 	/**
   801    * Generates HTML code for comments - used in browser compatibility mode
   801  	* Generates HTML code for comments - used in browser compatibility mode
   802    * @param $page_id the page ID
   802  	* @param $page_id the page ID
   803    * @param $namespace the namespace
   803  	* @param $namespace the namespace
   804    * @param $action administrative action to perform, default is false
   804  	* @param $action administrative action to perform, default is false
   805    * @param $flags additional info for $action, shouldn't be used except when deleting/approving comments, etc.
   805  	* @param $flags additional info for $action, shouldn't be used except when deleting/approving comments, etc.
   806    * @param $_ob text to prepend to output, used by PageUtils::addcomment
   806  	* @param $_ob text to prepend to output, used by PageUtils::addcomment
   807    * @return string
   807  	* @return string
   808    */
   808  	*/
   809   
   809 	
   810   public static function comments_html($page_id, $namespace, $action = false, $id = -1, $_ob = '')
   810 	public static function comments_html($page_id, $namespace, $action = false, $id = -1, $_ob = '')
   811   {
   811 	{
   812     global $db, $session, $paths, $template, $plugins; // Common objects
   812 		global $db, $session, $paths, $template, $plugins; // Common objects
   813     $r = PageUtils::comments_raw($page_id, $namespace, $action, $id, $_ob);
   813 		$r = PageUtils::comments_raw($page_id, $namespace, $action, $id, $_ob);
   814     return $r[1];
   814 		return $r[1];
   815   }
   815 	}
   816   
   816 	
   817   /**
   817 	/**
   818    * Updates comment data.
   818  	* Updates comment data.
   819    * @param $page_id the page ID
   819  	* @param $page_id the page ID
   820    * @param $namespace the namespace
   820  	* @param $namespace the namespace
   821    * @param $subject new subject
   821  	* @param $subject new subject
   822    * @param $text new text
   822  	* @param $text new text
   823    * @param $old_subject the old subject, unprocessed and identical to the value in the DB
   823  	* @param $old_subject the old subject, unprocessed and identical to the value in the DB
   824    * @param $old_text the old text, unprocessed and identical to the value in the DB
   824  	* @param $old_text the old text, unprocessed and identical to the value in the DB
   825    * @param $id the javascript list ID, used internally by the client-side app
   825  	* @param $id the javascript list ID, used internally by the client-side app
   826    * @return string
   826  	* @return string
   827    */
   827  	*/
   828   
   828 	
   829   public static function savecomment($page_id, $namespace, $subject, $text, $old_subject, $old_text, $id = -1)
   829 	public static function savecomment($page_id, $namespace, $subject, $text, $old_subject, $old_text, $id = -1)
   830   {
   830 	{
   831     global $db, $session, $paths, $template, $plugins; // Common objects
   831 		global $db, $session, $paths, $template, $plugins; // Common objects
   832     if(!$session->get_permissions('edit_comments'))
   832 		if(!$session->get_permissions('edit_comments'))
   833       return 'result="BAD";error="Access denied"';
   833 			return 'result="BAD";error="Access denied"';
   834     // Avoid SQL injection
   834 		// Avoid SQL injection
   835     $old_text    = $db->escape($old_text);
   835 		$old_text    = $db->escape($old_text);
   836     $old_subject = $db->escape($old_subject);
   836 		$old_subject = $db->escape($old_subject);
   837     // Safety check - username/login
   837 		// Safety check - username/login
   838     if(!$session->get_permissions('mod_comments')) // allow mods to edit comments
   838 		if(!$session->get_permissions('mod_comments')) // allow mods to edit comments
   839     {
   839 		{
   840       if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
   840 			if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
   841       $q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_data=\'' . $old_text . '\' AND subject=\'' . $old_subject . '\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
   841 			$q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_data=\'' . $old_text . '\' AND subject=\'' . $old_subject . '\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
   842       $s = $db->sql_query($q);
   842 			$s = $db->sql_query($q);
   843       if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
   843 			if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
   844       $r = $db->fetchrow($s);
   844 			$r = $db->fetchrow($s);
   845       $db->free_result();
   845 			$db->free_result();
   846       if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
   846 			if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
   847     }
   847 		}
   848     $s = RenderMan::preprocess_text($subject);
   848 		$s = RenderMan::preprocess_text($subject);
   849     $t = RenderMan::preprocess_text($text);
   849 		$t = RenderMan::preprocess_text($text);
   850     $sql  = 'UPDATE ' . table_prefix.'comments SET subject=\'' . $s . '\',comment_data=\'' . $t . '\' WHERE comment_data=\'' . $old_text . '\' AND subject=\'' . $old_subject . '\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
   850 		$sql  = 'UPDATE ' . table_prefix.'comments SET subject=\'' . $s . '\',comment_data=\'' . $t . '\' WHERE comment_data=\'' . $old_text . '\' AND subject=\'' . $old_subject . '\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
   851     $result = $db->sql_query($sql);
   851 		$result = $db->sql_query($sql);
   852     if($result)
   852 		if($result)
   853     {
   853 		{
   854       return 'result="GOOD";
   854 			return 'result="GOOD";
   855                       list[' . $id . '][\'subject\'] = unescape(\''.str_replace('%5Cn', '%0A', rawurlencode(str_replace('{{EnAnO:Newline}}', '\\n', stripslashes(str_replace('\\n', '{{EnAnO:Newline}}', $s))))).'\');
   855 											list[' . $id . '][\'subject\'] = unescape(\''.str_replace('%5Cn', '%0A', rawurlencode(str_replace('{{EnAnO:Newline}}', '\\n', stripslashes(str_replace('\\n', '{{EnAnO:Newline}}', $s))))).'\');
   856                       list[' . $id . '][\'comment\'] = unescape(\''.str_replace('%5Cn', '%0A', rawurlencode(str_replace('{{EnAnO:Newline}}', '\\n', stripslashes(str_replace('\\n', '{{EnAnO:Newline}}', $t))))).'\'); id = ' . $id . ';
   856 											list[' . $id . '][\'comment\'] = unescape(\''.str_replace('%5Cn', '%0A', rawurlencode(str_replace('{{EnAnO:Newline}}', '\\n', stripslashes(str_replace('\\n', '{{EnAnO:Newline}}', $t))))).'\'); id = ' . $id . ';
   857       s = unescape(\''.rawurlencode($s).'\');
   857 			s = unescape(\''.rawurlencode($s).'\');
   858       t = unescape(\''.str_replace('%5Cn', '<br \\/>', rawurlencode(RenderMan::render(str_replace('{{EnAnO:Newline}}', "\n", stripslashes(str_replace('\\n', '{{EnAnO:Newline}}', $t)))))).'\');';
   858 			t = unescape(\''.str_replace('%5Cn', '<br \\/>', rawurlencode(RenderMan::render(str_replace('{{EnAnO:Newline}}', "\n", stripslashes(str_replace('\\n', '{{EnAnO:Newline}}', $t)))))).'\');';
   859     }
   859 		}
   860     else
   860 		else
   861     {
   861 		{
   862       return 'result="BAD"; error=unescape("'.rawurlencode('Enano encountered a problem whilst saving the comment.
   862 			return 'result="BAD"; error=unescape("'.rawurlencode('Enano encountered a problem whilst saving the comment.
   863       Performed SQL:
   863 			Performed SQL:
   864       ' . $sql . '
   864 			' . $sql . '
   865     
   865 		
   866       Error returned by MySQL: '.$db->get_error()).'");';
   866 			Error returned by MySQL: '.$db->get_error()).'");';
   867     }
   867 		}
   868   }
   868 	}
   869   
   869 	
   870   /**
   870 	/**
   871    * Updates comment data using the comment_id column instead of the old, messy way
   871  	* Updates comment data using the comment_id column instead of the old, messy way
   872    * @param $page_id the page ID
   872  	* @param $page_id the page ID
   873    * @param $namespace the namespace
   873  	* @param $namespace the namespace
   874    * @param $subject new subject
   874  	* @param $subject new subject
   875    * @param $text new text
   875  	* @param $text new text
   876    * @param $id the comment ID (primary key in enano_comments table)
   876  	* @param $id the comment ID (primary key in enano_comments table)
   877    * @return string
   877  	* @return string
   878    */
   878  	*/
   879   
   879 	
   880   public static function savecomment_neater($page_id, $namespace, $subject, $text, $id)
   880 	public static function savecomment_neater($page_id, $namespace, $subject, $text, $id)
   881   {
   881 	{
   882     global $db, $session, $paths, $template, $plugins; // Common objects
   882 		global $db, $session, $paths, $template, $plugins; // Common objects
   883     if(!is_int($id)) die('PageUtils::savecomment: $id is not an integer, aborting for safety');
   883 		if(!is_int($id)) die('PageUtils::savecomment: $id is not an integer, aborting for safety');
   884     if(!$session->get_permissions('edit_comments'))
   884 		if(!$session->get_permissions('edit_comments'))
   885       return 'Access denied';
   885 			return 'Access denied';
   886     // Safety check - username/login
   886 		// Safety check - username/login
   887     if(!$session->get_permissions('mod_comments')) // allow mods to edit comments
   887 		if(!$session->get_permissions('mod_comments')) // allow mods to edit comments
   888     {
   888 		{
   889       if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
   889 			if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
   890       $q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_id=' . $id . ' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
   890 			$q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_id=' . $id . ' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
   891       $s = $db->sql_query($q);
   891 			$s = $db->sql_query($q);
   892       if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
   892 			if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
   893       $r = $db->fetchrow($s);
   893 			$r = $db->fetchrow($s);
   894       if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
   894 			if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
   895       $db->free_result();
   895 			$db->free_result();
   896     }
   896 		}
   897     $s = RenderMan::preprocess_text($subject);
   897 		$s = RenderMan::preprocess_text($subject);
   898     $t = RenderMan::preprocess_text($text);
   898 		$t = RenderMan::preprocess_text($text);
   899     $sql  = 'UPDATE ' . table_prefix.'comments SET subject=\'' . $s . '\',comment_data=\'' . $t . '\' WHERE comment_id=' . $id . ' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
   899 		$sql  = 'UPDATE ' . table_prefix.'comments SET subject=\'' . $s . '\',comment_data=\'' . $t . '\' WHERE comment_id=' . $id . ' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
   900     $result = $db->sql_query($sql);
   900 		$result = $db->sql_query($sql);
   901     if($result)
   901 		if($result)
   902     return 'good';
   902 		return 'good';
   903     else return 'Enano encountered a problem whilst saving the comment.
   903 		else return 'Enano encountered a problem whilst saving the comment.
   904     Performed SQL:
   904 		Performed SQL:
   905     ' . $sql . '
   905 		' . $sql . '
   906     
   906 		
   907     Error returned by MySQL: '.$db->get_error();
   907 		Error returned by MySQL: '.$db->get_error();
   908   }
   908 	}
   909   
   909 	
   910   /**
   910 	/**
   911    * Deletes a comment.
   911  	* Deletes a comment.
   912    * @param $page_id the page ID
   912  	* @param $page_id the page ID
   913    * @param $namespace the namespace
   913  	* @param $namespace the namespace
   914    * @param $name the name the user posted under
   914  	* @param $name the name the user posted under
   915    * @param $subj the subject of the comment to be deleted
   915  	* @param $subj the subject of the comment to be deleted
   916    * @param $text the text of the comment to be deleted
   916  	* @param $text the text of the comment to be deleted
   917    * @param $id the javascript list ID, used internally by the client-side app
   917  	* @param $id the javascript list ID, used internally by the client-side app
   918    * @return string
   918  	* @return string
   919    */
   919  	*/
   920   
   920 	
   921   public static function deletecomment($page_id, $namespace, $name, $subj, $text, $id)
   921 	public static function deletecomment($page_id, $namespace, $name, $subj, $text, $id)
   922   {
   922 	{
   923     global $db, $session, $paths, $template, $plugins; // Common objects
   923 		global $db, $session, $paths, $template, $plugins; // Common objects
   924     
   924 		
   925     if(!$session->get_permissions('edit_comments'))
   925 		if(!$session->get_permissions('edit_comments'))
   926       return 'alert("Access to delete/edit comments is denied");';
   926 			return 'alert("Access to delete/edit comments is denied");';
   927     
   927 		
   928     if(!preg_match('#^([0-9]+)$#', (string)$id)) die('$_GET[id] is improperly formed.');
   928 		if(!preg_match('#^([0-9]+)$#', (string)$id)) die('$_GET[id] is improperly formed.');
   929     $n = $db->escape($name);
   929 		$n = $db->escape($name);
   930     $s = $db->escape($subj);
   930 		$s = $db->escape($subj);
   931     $t = $db->escape($text);
   931 		$t = $db->escape($text);
   932     
   932 		
   933     // Safety check - username/login
   933 		// Safety check - username/login
   934     if(!$session->get_permissions('mod_comments')) // allows mods to delete comments
   934 		if(!$session->get_permissions('mod_comments')) // allows mods to delete comments
   935     {
   935 		{
   936       if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
   936 			if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
   937       $q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_data=\'' . $t . '\' AND subject=\'' . $s . '\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
   937 			$q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_data=\'' . $t . '\' AND subject=\'' . $s . '\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
   938       $s = $db->sql_query($q);
   938 			$s = $db->sql_query($q);
   939       if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
   939 			if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
   940       $r = $db->fetchrow($s);
   940 			$r = $db->fetchrow($s);
   941       if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
   941 			if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
   942       $db->free_result();
   942 			$db->free_result();
   943     }
   943 		}
   944     $q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND name=\'' . $n . '\' AND subject=\'' . $s . '\' AND comment_data=\'' . $t . '\' LIMIT 1;';
   944 		$q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND name=\'' . $n . '\' AND subject=\'' . $s . '\' AND comment_data=\'' . $t . '\' LIMIT 1;';
   945     $e=$db->sql_query($q);
   945 		$e=$db->sql_query($q);
   946     if(!$e) return('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   946 		if(!$e) return('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   947     return('good');
   947 		return('good');
   948   }
   948 	}
   949   
   949 	
   950   /**
   950 	/**
   951    * Deletes a comment in a cleaner fashion.
   951  	* Deletes a comment in a cleaner fashion.
   952    * @param $page_id the page ID
   952  	* @param $page_id the page ID
   953    * @param $namespace the namespace
   953  	* @param $namespace the namespace
   954    * @param $id the comment ID (primary key)
   954  	* @param $id the comment ID (primary key)
   955    * @return string
   955  	* @return string
   956    */
   956  	*/
   957   
   957 	
   958   public static function deletecomment_neater($page_id, $namespace, $id)
   958 	public static function deletecomment_neater($page_id, $namespace, $id)
   959   {
   959 	{
   960     global $db, $session, $paths, $template, $plugins; // Common objects
   960 		global $db, $session, $paths, $template, $plugins; // Common objects
   961     
   961 		
   962     if(!preg_match('#^([0-9]+)$#', (string)$id)) die('$_GET[id] is improperly formed.');
   962 		if(!preg_match('#^([0-9]+)$#', (string)$id)) die('$_GET[id] is improperly formed.');
   963     
   963 		
   964     if(!$session->get_permissions('edit_comments'))
   964 		if(!$session->get_permissions('edit_comments'))
   965       return 'alert("Access to delete/edit comments is denied");';
   965 			return 'alert("Access to delete/edit comments is denied");';
   966     
   966 		
   967     // Safety check - username/login
   967 		// Safety check - username/login
   968     if(!$session->get_permissions('mod_comments')) // allows mods to delete comments
   968 		if(!$session->get_permissions('mod_comments')) // allows mods to delete comments
   969     {
   969 		{
   970       if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
   970 			if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
   971       $q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_id=' . $id . ' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
   971 			$q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_id=' . $id . ' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
   972       $s = $db->sql_query($q);
   972 			$s = $db->sql_query($q);
   973       if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
   973 			if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
   974       $r = $db->fetchrow($s);
   974 			$r = $db->fetchrow($s);
   975       if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
   975 			if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
   976       $db->free_result();
   976 			$db->free_result();
   977     }
   977 		}
   978     $q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND comment_id=' . $id . ' LIMIT 1;';
   978 		$q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND comment_id=' . $id . ' LIMIT 1;';
   979     $e=$db->sql_query($q);
   979 		$e=$db->sql_query($q);
   980     if(!$e) return('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   980 		if(!$e) return('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
   981     return('good');
   981 		return('good');
   982   }
   982 	}
   983   
   983 	
   984   /**
   984 	/**
   985    * Renames a page.
   985  	* Renames a page.
   986    * @param $page_id the page ID
   986  	* @param $page_id the page ID
   987    * @param $namespace the namespace
   987  	* @param $namespace the namespace
   988    * @param $name the new name for the page
   988  	* @param $name the new name for the page
   989    * @return string error string or success message
   989  	* @return string error string or success message
   990    */
   990  	*/
   991    
   991  	
   992   public static function rename($page_id, $namespace, $name)
   992 	public static function rename($page_id, $namespace, $name)
   993   {
   993 	{
   994     global $db, $session, $paths, $template, $plugins; // Common objects
   994 		global $db, $session, $paths, $template, $plugins; // Common objects
   995     global $lang;
   995 		global $lang;
   996     
   996 		
   997     $page = new PageProcessor($page_id, $namespace);
   997 		$page = new PageProcessor($page_id, $namespace);
   998     return $page->rename_page($name);
   998 		return $page->rename_page($name);
   999   }
   999 	}
  1000   
  1000 	
  1001   /**
  1001 	/**
  1002    * Flushes (clears) the action logs for a given page
  1002  	* Flushes (clears) the action logs for a given page
  1003    * @param $page_id the page ID
  1003  	* @param $page_id the page ID
  1004    * @param $namespace the namespace
  1004  	* @param $namespace the namespace
  1005    * @return string error/success string
  1005  	* @return string error/success string
  1006    */
  1006  	*/
  1007    
  1007  	
  1008   public static function flushlogs($page_id, $namespace)
  1008 	public static function flushlogs($page_id, $namespace)
  1009   {
  1009 	{
  1010     global $db, $session, $paths, $template, $plugins; // Common objects
  1010 		global $db, $session, $paths, $template, $plugins; // Common objects
  1011     global $lang;
  1011 		global $lang;
  1012     if ( !is_object($lang) && defined('IN_ENANO_INSTALL') )
  1012 		if ( !is_object($lang) && defined('IN_ENANO_INSTALL') )
  1013     {
  1013 		{
  1014       // This is a special exception for the Enano installer, which doesn't init languages yet.
  1014 			// This is a special exception for the Enano installer, which doesn't init languages yet.
  1015       $lang = new Language('eng');
  1015 			$lang = new Language('eng');
  1016     }
  1016 		}
  1017     if(!$session->get_permissions('clear_logs') && !defined('IN_ENANO_INSTALL'))
  1017 		if(!$session->get_permissions('clear_logs') && !defined('IN_ENANO_INSTALL'))
  1018     {
  1018 		{
  1019       return $lang->get('etc_access_denied');
  1019 			return $lang->get('etc_access_denied');
  1020     }
  1020 		}
  1021     if ( !$session->sid_super )
  1021 		if ( !$session->sid_super )
  1022     {
  1022 		{
  1023       return $lang->get('etc_access_denied_need_reauth');
  1023 			return $lang->get('etc_access_denied_need_reauth');
  1024     }
  1024 		}
  1025     
  1025 		
  1026     $page_id_db = $db->escape($page_id);
  1026 		$page_id_db = $db->escape($page_id);
  1027     $namespace_db = $db->escape($namespace);
  1027 		$namespace_db = $db->escape($namespace);
  1028     
  1028 		
  1029     // If we're flushing a file, also clear all revisions before the current
  1029 		// If we're flushing a file, also clear all revisions before the current
  1030     if ( $namespace == 'File' )
  1030 		if ( $namespace == 'File' )
  1031     {
  1031 		{
  1032       $q = $db->sql_query('SELECT file_id FROM ' . table_prefix . "files WHERE page_id='$page_id_db' ORDER BY time_id DESC;");
  1032 			$q = $db->sql_query('SELECT file_id FROM ' . table_prefix . "files WHERE page_id='$page_id_db' ORDER BY time_id DESC;");
  1033       if ( !$q )
  1033 			if ( !$q )
  1034         $db->_die();
  1034 				$db->_die();
  1035       // discard first row (current revision)
  1035 			// discard first row (current revision)
  1036       $db->fetchrow();
  1036 			$db->fetchrow();
  1037       $id_list = array();
  1037 			$id_list = array();
  1038       while ( $row = $db->fetchrow() )
  1038 			while ( $row = $db->fetchrow() )
  1039         $id_list[] = $row['file_id'];
  1039 				$id_list[] = $row['file_id'];
  1040       
  1040 			
  1041       require_once(ENANO_ROOT . '/includes/namespaces/file.php');
  1041 			require_once(ENANO_ROOT . '/includes/namespaces/file.php');
  1042       
  1042 			
  1043       // clear out each file
  1043 			// clear out each file
  1044       foreach ( $id_list as $id )
  1044 			foreach ( $id_list as $id )
  1045         Namespace_File::delete_file($id);
  1045 				Namespace_File::delete_file($id);
  1046     }
  1046 		}
  1047     
  1047 		
  1048     $q = $db->sql_query('DELETE FROM ' . table_prefix . "logs WHERE page_id='$page_id_db' AND namespace='$namespace';");
  1048 		$q = $db->sql_query('DELETE FROM ' . table_prefix . "logs WHERE page_id='$page_id_db' AND namespace='$namespace';");
  1049     if ( !$q )
  1049 		if ( !$q )
  1050       $db->_die('The log entries could not be deleted.');
  1050 			$db->_die('The log entries could not be deleted.');
  1051     
  1051 		
  1052     // If the page exists, make a backup of it in case it gets spammed/vandalized
  1052 		// If the page exists, make a backup of it in case it gets spammed/vandalized
  1053     // If not, the admin's probably deleting a trash page
  1053 		// If not, the admin's probably deleting a trash page
  1054     if ( isPage($paths->get_pathskey($page_id, $namespace)) )
  1054 		if ( isPage($paths->get_pathskey($page_id, $namespace)) )
  1055     {
  1055 		{
  1056       $q = $db->sql_query('SELECT page_text,char_tag FROM ' . table_prefix . "page_text WHERE page_id='$page_id_db' AND namespace='$namespace_db';");
  1056 			$q = $db->sql_query('SELECT page_text,char_tag FROM ' . table_prefix . "page_text WHERE page_id='$page_id_db' AND namespace='$namespace_db';");
  1057       if ( !$q )
  1057 			if ( !$q )
  1058         $db->_die('The current page text could not be selected; as a result, creating the backup of the page failed. Please make a backup copy of the page by clicking Edit this page and then clicking Save Changes.');
  1058 				$db->_die('The current page text could not be selected; as a result, creating the backup of the page failed. Please make a backup copy of the page by clicking Edit this page and then clicking Save Changes.');
  1059       $row = $db->fetchrow();
  1059 			$row = $db->fetchrow();
  1060       $db->free_result();
  1060 			$db->free_result();
  1061       $minor_edit = ( ENANO_DBLAYER == 'MYSQL' ) ? 'false' : '0';
  1061 			$minor_edit = ( ENANO_DBLAYER == 'MYSQL' ) ? 'false' : '0';
  1062       $username = $db->escape($session->username);
  1062 			$username = $db->escape($session->username);
  1063       $q = 'INSERT INTO ' . table_prefix . "logs ( log_type, action, time_id, date_string, page_id, namespace, page_text, char_tag, author, author_uid, edit_summary, minor_edit ) VALUES\n"
  1063 			$q = 'INSERT INTO ' . table_prefix . "logs ( log_type, action, time_id, date_string, page_id, namespace, page_text, char_tag, author, author_uid, edit_summary, minor_edit ) VALUES\n"
  1064          . "  ('page', 'edit', " . time() . ", 'DEPRECATED', '$page_id', '$namespace', '" . $db->escape($row['page_text']) . "', '', '{$username}', $session->user_id, '" . $lang->get('page_flushlogs_backup_summary') . "', $minor_edit);";
  1064  				. "  ('page', 'edit', " . time() . ", 'DEPRECATED', '$page_id', '$namespace', '" . $db->escape($row['page_text']) . "', '', '{$username}', $session->user_id, '" . $lang->get('page_flushlogs_backup_summary') . "', $minor_edit);";
  1065       if ( !$db->sql_query($q) )
  1065 			if ( !$db->sql_query($q) )
  1066         $db->_die('The history (log) entry could not be inserted into the logs table.');
  1066 				$db->_die('The history (log) entry could not be inserted into the logs table.');
  1067     }
  1067 		}
  1068     
  1068 		
  1069     return $lang->get('ajax_clearlogs_success');
  1069 		return $lang->get('ajax_clearlogs_success');
  1070   }
  1070 	}
  1071   
  1071 	
  1072   /**
  1072 	/**
  1073    * Deletes a page.
  1073  	* Deletes a page.
  1074    * @param string $page_id the condemned page ID
  1074  	* @param string $page_id the condemned page ID
  1075    * @param string $namespace the condemned namespace
  1075  	* @param string $namespace the condemned namespace
  1076    * @param string The reason for deleting the page in question
  1076  	* @param string The reason for deleting the page in question
  1077    * @return string
  1077  	* @return string
  1078    */
  1078  	*/
  1079    
  1079  	
  1080   public static function deletepage($page_id, $namespace, $reason)
  1080 	public static function deletepage($page_id, $namespace, $reason)
  1081   {
  1081 	{
  1082     global $db, $session, $paths, $template, $plugins; // Common objects
  1082 		global $db, $session, $paths, $template, $plugins; // Common objects
  1083     global $lang;
  1083 		global $lang;
  1084     global $cache;
  1084 		global $cache;
  1085     $perms = $session->fetch_page_acl($page_id, $namespace);
  1085 		$perms = $session->fetch_page_acl($page_id, $namespace);
  1086     $x = trim($reason);
  1086 		$x = trim($reason);
  1087     if ( empty($x) )
  1087 		if ( empty($x) )
  1088     {
  1088 		{
  1089       return $lang->get('ajax_delete_need_reason');
  1089 			return $lang->get('ajax_delete_need_reason');
  1090     }
  1090 		}
  1091     if(!$perms->get_permissions('delete_page')) return('Administrative privileges are required to delete pages, you loser.');
  1091 		if(!$perms->get_permissions('delete_page')) return('Administrative privileges are required to delete pages, you loser.');
  1092     
  1092 		
  1093     if ( !$session->sid_super )
  1093 		if ( !$session->sid_super )
  1094     {
  1094 		{
  1095       return $lang->get('etc_access_denied_need_reauth');
  1095 			return $lang->get('etc_access_denied_need_reauth');
  1096     }
  1096 		}
  1097     
  1097 		
  1098     $e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,author_uid,edit_summary) VALUES('.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \'page\', \'delete\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $session->username . '\', ' . $session->user_id . ', \'' . $db->escape(htmlspecialchars($reason)) . '\')');
  1098 		$e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,author_uid,edit_summary) VALUES('.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \'page\', \'delete\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $session->username . '\', ' . $session->user_id . ', \'' . $db->escape(htmlspecialchars($reason)) . '\')');
  1099     if(!$e) $db->_die('The page log entry could not be inserted.');
  1099 		if(!$e) $db->_die('The page log entry could not be inserted.');
  1100     $e = $db->sql_query('DELETE FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
  1100 		$e = $db->sql_query('DELETE FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
  1101     if(!$e) $db->_die('The page categorization entries could not be deleted.');
  1101 		if(!$e) $db->_die('The page categorization entries could not be deleted.');
  1102     $e = $db->sql_query('DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
  1102 		$e = $db->sql_query('DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
  1103     if(!$e) $db->_die('The page comments could not be deleted.');
  1103 		if(!$e) $db->_die('The page comments could not be deleted.');
  1104     $e = $db->sql_query('DELETE FROM ' . table_prefix.'page_text WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
  1104 		$e = $db->sql_query('DELETE FROM ' . table_prefix.'page_text WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
  1105     if(!$e) $db->_die('The page text entry could not be deleted.');
  1105 		if(!$e) $db->_die('The page text entry could not be deleted.');
  1106     $e = $db->sql_query('DELETE FROM ' . table_prefix.'pages WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
  1106 		$e = $db->sql_query('DELETE FROM ' . table_prefix.'pages WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
  1107     if(!$e) $db->_die('The page entry could not be deleted.');
  1107 		if(!$e) $db->_die('The page entry could not be deleted.');
  1108     if ( $namespace == 'File' )
  1108 		if ( $namespace == 'File' )
  1109     {
  1109 		{
  1110       $e = $db->sql_query('DELETE FROM ' . table_prefix.'files WHERE page_id=\'' . $page_id . '\'');
  1110 			$e = $db->sql_query('DELETE FROM ' . table_prefix.'files WHERE page_id=\'' . $page_id . '\'');
  1111       if(!$e) $db->_die('The file entry could not be deleted.');
  1111 			if(!$e) $db->_die('The file entry could not be deleted.');
  1112     }
  1112 		}
  1113     $cache->purge('page_meta');
  1113 		$cache->purge('page_meta');
  1114     return $lang->get('ajax_delete_success');
  1114 		return $lang->get('ajax_delete_success');
  1115   }
  1115 	}
  1116   
  1116 	
  1117   /**
  1117 	/**
  1118    * Deletes files associated with a File page.
  1118  	* Deletes files associated with a File page.
  1119    * @param string Page ID
  1119  	* @param string Page ID
  1120    */
  1120  	*/
  1121   
  1121 	
  1122   public static function delete_page_files($page_id)
  1122 	public static function delete_page_files($page_id)
  1123   {
  1123 	{
  1124     global $db, $session, $paths, $template, $plugins; // Common objects
  1124 		global $db, $session, $paths, $template, $plugins; // Common objects
  1125     
  1125 		
  1126     $q = $db->sql_query('SELECT file_id, filename, file_key, time_id, file_extension FROM ' . table_prefix . "files WHERE page_id = '{$db->escape($page_id)}';");
  1126 		$q = $db->sql_query('SELECT file_id, filename, file_key, time_id, file_extension FROM ' . table_prefix . "files WHERE page_id = '{$db->escape($page_id)}';");
  1127     if ( !$q )
  1127 		if ( !$q )
  1128       $db->_die();
  1128 			$db->_die();
  1129     
  1129 		
  1130     while ( $row = $db->fetchrow() )
  1130 		while ( $row = $db->fetchrow() )
  1131     {
  1131 		{
  1132       // wipe original file
  1132 			// wipe original file
  1133       foreach ( array(
  1133 			foreach ( array(
  1134           ENANO_ROOT . "/files/{$row['file_key']}_{$row['time_id']}{$row['file_extension']}",
  1134 					ENANO_ROOT . "/files/{$row['file_key']}_{$row['time_id']}{$row['file_extension']}",
  1135           ENANO_ROOT . "/files/{$row['file_key']}{$row['file_extension']}"
  1135 					ENANO_ROOT . "/files/{$row['file_key']}{$row['file_extension']}"
  1136         ) as $orig_file )
  1136 				) as $orig_file )
  1137       {
  1137 			{
  1138         if ( file_exists($orig_file) )
  1138 				if ( file_exists($orig_file) )
  1139           @unlink($orig_file);
  1139 					@unlink($orig_file);
  1140       }
  1140 			}
  1141       
  1141 			
  1142       // wipe cached files
  1142 			// wipe cached files
  1143       if ( $dr = @opendir(ENANO_ROOT . '/cache/') )
  1143 			if ( $dr = @opendir(ENANO_ROOT . '/cache/') )
  1144       {
  1144 			{
  1145         // lol404.jpg-1217958283-200x320.jpg
  1145 				// lol404.jpg-1217958283-200x320.jpg
  1146         while ( $dh = @readdir($dr) )
  1146 				while ( $dh = @readdir($dr) )
  1147         {
  1147 				{
  1148           $regexp = ':^' . preg_quote("{$row['filename']}-{$row['time_id']}-") . '[0-9]+x[0-9]+\.' . ltrim($row['file_extension'], '.') . '$:';
  1148 					$regexp = ':^' . preg_quote("{$row['filename']}-{$row['time_id']}-") . '[0-9]+x[0-9]+\.' . ltrim($row['file_extension'], '.') . '$:';
  1149           if ( preg_match($regexp, $dh) )
  1149 					if ( preg_match($regexp, $dh) )
  1150           {
  1150 					{
  1151             @unlink(ENANO_ROOT . "/cache/$dh");
  1151 						@unlink(ENANO_ROOT . "/cache/$dh");
  1152           }
  1152 					}
  1153         }
  1153 				}
  1154         @closedir($dr);
  1154 				@closedir($dr);
  1155       }
  1155 			}
  1156     }
  1156 		}
  1157     
  1157 		
  1158     $q = $db->sql_query('DELETE FROM ' . table_prefix . "files WHERE page_id = '{$db->escape($page_id)}';");
  1158 		$q = $db->sql_query('DELETE FROM ' . table_prefix . "files WHERE page_id = '{$db->escape($page_id)}';");
  1159     if ( !$q )
  1159 		if ( !$q )
  1160       $db->die();
  1160 			$db->die();
  1161     
  1161 		
  1162     return true;
  1162 		return true;
  1163   }
  1163 	}
  1164   
  1164 	
  1165   /**
  1165 	/**
  1166    * Increments the deletion votes for a page by 1, and adds the current username/IP to the list of users that have voted for the page to prevent dual-voting
  1166  	* Increments the deletion votes for a page by 1, and adds the current username/IP to the list of users that have voted for the page to prevent dual-voting
  1167    * @param $page_id the page ID
  1167  	* @param $page_id the page ID
  1168    * @param $namespace the namespace
  1168  	* @param $namespace the namespace
  1169    * @return string
  1169  	* @return string
  1170    */
  1170  	*/
  1171    
  1171  	
  1172   public static function delvote($page_id, $namespace)
  1172 	public static function delvote($page_id, $namespace)
  1173   {
  1173 	{
  1174     global $db, $session, $paths, $template, $plugins; // Common objects
  1174 		global $db, $session, $paths, $template, $plugins; // Common objects
  1175     global $lang;
  1175 		global $lang;
  1176     global $cache;
  1176 		global $cache;
  1177     
  1177 		
  1178     if ( !$session->get_permissions('vote_delete') )
  1178 		if ( !$session->get_permissions('vote_delete') )
  1179     {
  1179 		{
  1180       return $lang->get('etc_access_denied');
  1180 			return $lang->get('etc_access_denied');
  1181     }
  1181 		}
  1182     
  1182 		
  1183     if ( $namespace == 'Admin' || $namespace == 'Special' || $namespace == 'System' )
  1183 		if ( $namespace == 'Admin' || $namespace == 'Special' || $namespace == 'System' )
  1184     {
  1184 		{
  1185       return 'Special pages and system messages can\'t be voted for deletion.';
  1185 			return 'Special pages and system messages can\'t be voted for deletion.';
  1186     }
  1186 		}
  1187     
  1187 		
  1188     $pname = $paths->nslist[$namespace] . sanitize_page_id($page_id);
  1188 		$pname = $paths->nslist[$namespace] . sanitize_page_id($page_id);
  1189     
  1189 		
  1190     if ( !isPage($pname) )
  1190 		if ( !isPage($pname) )
  1191     {
  1191 		{
  1192       return 'The page does not exist.';
  1192 			return 'The page does not exist.';
  1193     }
  1193 		}
  1194     
  1194 		
  1195     $ns = namespace_factory($page_id, $namespace);
  1195 		$ns = namespace_factory($page_id, $namespace);
  1196     $cdata = $ns->get_cdata();
  1196 		$cdata = $ns->get_cdata();
  1197     
  1197 		
  1198     $cv  =& $cdata['delvotes'];
  1198 		$cv  =& $cdata['delvotes'];
  1199     $ips =& $cdata['delvote_ips'];
  1199 		$ips =& $cdata['delvote_ips'];
  1200     
  1200 		
  1201     if ( empty($ips) )
  1201 		if ( empty($ips) )
  1202     {
  1202 		{
  1203       $ips = array(
  1203 			$ips = array(
  1204         'ip' => array(),
  1204 				'ip' => array(),
  1205         'u' => array()
  1205 				'u' => array()
  1206         );
  1206 				);
  1207     }
  1207 		}
  1208     else
  1208 		else
  1209     {
  1209 		{
  1210       $ips = @unserialize($ips);
  1210 			$ips = @unserialize($ips);
  1211       if ( !$ips )
  1211 			if ( !$ips )
  1212       {
  1212 			{
  1213         $ips = array(
  1213 				$ips = array(
  1214         'ip' => array(),
  1214 				'ip' => array(),
  1215         'u' => array()
  1215 				'u' => array()
  1216         );
  1216 				);
  1217       }
  1217 			}
  1218     }
  1218 		}
  1219     
  1219 		
  1220     if ( in_array($session->username, $ips['u']) || in_array($_SERVER['REMOTE_ADDR'], $ips['ip']) )
  1220 		if ( in_array($session->username, $ips['u']) || in_array($_SERVER['REMOTE_ADDR'], $ips['ip']) )
  1221     {
  1221 		{
  1222       return $lang->get('ajax_delvote_already_voted');
  1222 			return $lang->get('ajax_delvote_already_voted');
  1223     }
  1223 		}
  1224     
  1224 		
  1225     $ips['u'][] = $session->username;
  1225 		$ips['u'][] = $session->username;
  1226     $ips['ip'][] = $_SERVER['REMOTE_ADDR'];
  1226 		$ips['ip'][] = $_SERVER['REMOTE_ADDR'];
  1227     $ips = $db->escape( serialize($ips) );
  1227 		$ips = $db->escape( serialize($ips) );
  1228     
  1228 		
  1229     $cv++;
  1229 		$cv++;
  1230     
  1230 		
  1231     $q = 'UPDATE ' . table_prefix.'pages SET delvotes=' . $cv . ',delvote_ips=\'' . $ips . '\' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
  1231 		$q = 'UPDATE ' . table_prefix.'pages SET delvotes=' . $cv . ',delvote_ips=\'' . $ips . '\' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
  1232     $w = $db->sql_query($q);
  1232 		$w = $db->sql_query($q);
  1233     if ( !$w )
  1233 		if ( !$w )
  1234       $db->_die();
  1234 			$db->_die();
  1235     
  1235 		
  1236     // all done, flush page cache to mark it up
  1236 		// all done, flush page cache to mark it up
  1237     $cache->purge('page_meta');
  1237 		$cache->purge('page_meta');
  1238     
  1238 		
  1239     return $lang->get('ajax_delvote_success');
  1239 		return $lang->get('ajax_delvote_success');
  1240   }
  1240 	}
  1241   
  1241 	
  1242   /**
  1242 	/**
  1243    * Resets the number of votes against a page to 0.
  1243  	* Resets the number of votes against a page to 0.
  1244    * @param $page_id the page ID
  1244  	* @param $page_id the page ID
  1245    * @param $namespace the namespace
  1245  	* @param $namespace the namespace
  1246    * @return string
  1246  	* @return string
  1247    */
  1247  	*/
  1248   
  1248 	
  1249   public static function resetdelvotes($page_id, $namespace)
  1249 	public static function resetdelvotes($page_id, $namespace)
  1250   {
  1250 	{
  1251     global $db, $session, $paths, $template, $plugins; // Common objects
  1251 		global $db, $session, $paths, $template, $plugins; // Common objects
  1252     global $lang;
  1252 		global $lang;
  1253     global $cache;
  1253 		global $cache;
  1254     
  1254 		
  1255     if ( !$session->get_permissions('vote_reset') )
  1255 		if ( !$session->get_permissions('vote_reset') )
  1256     {
  1256 		{
  1257       return $lang->get('etc_access_denied');
  1257 			return $lang->get('etc_access_denied');
  1258     }
  1258 		}
  1259     
  1259 		
  1260     $page_id = $db->escape($page_id);
  1260 		$page_id = $db->escape($page_id);
  1261     $namespace = $db->escape($namespace);
  1261 		$namespace = $db->escape($namespace);
  1262     
  1262 		
  1263     // pull existing info
  1263 		// pull existing info
  1264     $q = $db->sql_query('SELECT delvotes, delvote_ips FROM ' . table_prefix . "pages WHERE urlname = '$page_id' AND namespace = '$namespace'");
  1264 		$q = $db->sql_query('SELECT delvotes, delvote_ips FROM ' . table_prefix . "pages WHERE urlname = '$page_id' AND namespace = '$namespace'");
  1265     if ( !$q )
  1265 		if ( !$q )
  1266       $db->_die();
  1266 			$db->_die();
  1267     if ( $db->numrows() < 1 )
  1267 		if ( $db->numrows() < 1 )
  1268       return $lang->get('page_err_page_not_exist');
  1268 			return $lang->get('page_err_page_not_exist');
  1269     
  1269 		
  1270     list($delvotes, $delvote_ips) = $db->fetchrow_num();
  1270 		list($delvotes, $delvote_ips) = $db->fetchrow_num();
  1271     $db->free_result();
  1271 		$db->free_result();
  1272     $delvote_ips = $db->escape($delvote_ips);
  1272 		$delvote_ips = $db->escape($delvote_ips);
  1273     $username = $db->escape($session->username);
  1273 		$username = $db->escape($session->username);
  1274     
  1274 		
  1275     // log action
  1275 		// log action
  1276     $time = time();
  1276 		$time = time();
  1277     $q = $db->sql_query('INSERT INTO ' . table_prefix . "logs (time_id, log_type, action, edit_summary, page_text, author, author_uid, page_id, namespace) VALUES\n"
  1277 		$q = $db->sql_query('INSERT INTO ' . table_prefix . "logs (time_id, log_type, action, edit_summary, page_text, author, author_uid, page_id, namespace) VALUES\n"
  1278                       . "  ( $time, 'page', 'votereset', '$delvotes', '$delvote_ips', '$username', $session->user_id, '$page_id', '$namespace' )");
  1278 											. "  ( $time, 'page', 'votereset', '$delvotes', '$delvote_ips', '$username', $session->user_id, '$page_id', '$namespace' )");
  1279     if ( !$q )
  1279 		if ( !$q )
  1280       $db->_die();
  1280 			$db->_die();
  1281     
  1281 		
  1282     // reset votes
  1282 		// reset votes
  1283     $empty_vote_record = $db->escape(serialize(array('ip'=>array(),'u'=>array())));
  1283 		$empty_vote_record = $db->escape(serialize(array('ip'=>array(),'u'=>array())));
  1284     $q = 'UPDATE ' . table_prefix.'pages SET delvotes=0,delvote_ips=\'' . $empty_vote_record . '\' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
  1284 		$q = 'UPDATE ' . table_prefix.'pages SET delvotes=0,delvote_ips=\'' . $empty_vote_record . '\' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
  1285     $e = $db->sql_query($q);
  1285 		$e = $db->sql_query($q);
  1286     if ( !$e )
  1286 		if ( !$e )
  1287     {
  1287 		{
  1288       $db->_die('The number of delete votes was not reset.');
  1288 			$db->_die('The number of delete votes was not reset.');
  1289     }
  1289 		}
  1290     else
  1290 		else
  1291     {
  1291 		{
  1292       $cache->purge('page_meta');
  1292 			$cache->purge('page_meta');
  1293       return $lang->get('ajax_delvote_reset_success');
  1293 			return $lang->get('ajax_delvote_reset_success');
  1294     }
  1294 		}
  1295   }
  1295 	}
  1296   
  1296 	
  1297   /**
  1297 	/**
  1298    * Gets a list of styles for a given theme name. As of Banshee, this returns JSON.
  1298  	* Gets a list of styles for a given theme name. As of Banshee, this returns JSON.
  1299    * @param $id the name of the directory for the theme
  1299  	* @param $id the name of the directory for the theme
  1300    * @return string JSON string with an array containing a list of themes
  1300  	* @return string JSON string with an array containing a list of themes
  1301    */
  1301  	*/
  1302    
  1302  	
  1303   public static function getstyles()
  1303 	public static function getstyles()
  1304   {
  1304 	{
  1305     
  1305 		
  1306     if ( !preg_match('/^([a-z0-9_-]+)$/', $_GET['id']) )
  1306 		if ( !preg_match('/^([a-z0-9_-]+)$/', $_GET['id']) )
  1307       return enano_json_encode(false);
  1307 			return enano_json_encode(false);
  1308     
  1308 		
  1309     $dir = './themes/' . $_GET['id'] . '/css/';
  1309 		$dir = './themes/' . $_GET['id'] . '/css/';
  1310     $list = Array();
  1310 		$list = Array();
  1311     // Open a known directory, and proceed to read its contents
  1311 		// Open a known directory, and proceed to read its contents
  1312     if (is_dir($dir)) {
  1312 		if (is_dir($dir)) {
  1313       if ($dh = opendir($dir)) {
  1313 			if ($dh = opendir($dir)) {
  1314         while (($file = readdir($dh)) !== false) {
  1314 				while (($file = readdir($dh)) !== false) {
  1315           if ( preg_match('#^(.*?)\.css$#is', $file) && $file != '_printable.css' ) // _printable.css should be included with every theme
  1315 					if ( preg_match('#^(.*?)\.css$#is', $file) && $file != '_printable.css' ) // _printable.css should be included with every theme
  1316           {                                                                         // it should be a copy of the original style, but
  1316 					{                                                                         // it should be a copy of the original style, but
  1317                                                                                     // mostly black and white
  1317 																																										// mostly black and white
  1318                                                                                     // Note to self: document this
  1318 																																										// Note to self: document this
  1319             $list[] = substr($file, 0, strlen($file)-4);
  1319 						$list[] = substr($file, 0, strlen($file)-4);
  1320           }
  1320 					}
  1321         }
  1321 				}
  1322         closedir($dh);
  1322 				closedir($dh);
  1323       }
  1323 			}
  1324     }
  1324 		}
  1325     else
  1325 		else
  1326     {
  1326 		{
  1327       return(enano_json_encode(Array('mode' => 'error', 'error' => $dir.' is not a dir')));
  1327 			return(enano_json_encode(Array('mode' => 'error', 'error' => $dir.' is not a dir')));
  1328     }
  1328 		}
  1329     
  1329 		
  1330     return enano_json_encode($list);
  1330 		return enano_json_encode($list);
  1331   }
  1331 	}
  1332   
  1332 	
  1333   /**
  1333 	/**
  1334    * Assembles a Javascript app with category information
  1334  	* Assembles a Javascript app with category information
  1335    * @param $page_id the page ID
  1335  	* @param $page_id the page ID
  1336    * @param $namespace the namespace
  1336  	* @param $namespace the namespace
  1337    * @return string Javascript code
  1337  	* @return string Javascript code
  1338    */
  1338  	*/
  1339    
  1339  	
  1340   public static function catedit($page_id, $namespace)
  1340 	public static function catedit($page_id, $namespace)
  1341   {
  1341 	{
  1342     $d = PageUtils::catedit_raw($page_id, $namespace);
  1342 		$d = PageUtils::catedit_raw($page_id, $namespace);
  1343     return $d[0] . ' /* BEGIN CONTENT */ document.getElementById("ajaxEditContainer").innerHTML = unescape(\''.rawurlencode($d[1]).'\');';
  1343 		return $d[0] . ' /* BEGIN CONTENT */ document.getElementById("ajaxEditContainer").innerHTML = unescape(\''.rawurlencode($d[1]).'\');';
  1344   }
  1344 	}
  1345   
  1345 	
  1346   /**
  1346 	/**
  1347    * Does the actual HTML/javascript generation for cat editing, but returns an array
  1347  	* Does the actual HTML/javascript generation for cat editing, but returns an array
  1348    * @access private
  1348  	* @access private
  1349    */
  1349  	*/
  1350    
  1350  	
  1351   public static function catedit_raw($page_id, $namespace)
  1351 	public static function catedit_raw($page_id, $namespace)
  1352   {
  1352 	{
  1353     global $db, $session, $paths, $template, $plugins; // Common objects
  1353 		global $db, $session, $paths, $template, $plugins; // Common objects
  1354     global $lang;
  1354 		global $lang;
  1355     
  1355 		
  1356     ob_start();
  1356 		ob_start();
  1357     $_ob = '';
  1357 		$_ob = '';
  1358     $e = $db->sql_query('SELECT category_id FROM ' . table_prefix.'categories WHERE page_id=\'' . $paths->page_id . '\' AND namespace=\'' . $paths->namespace . '\'');
  1358 		$e = $db->sql_query('SELECT category_id FROM ' . table_prefix.'categories WHERE page_id=\'' . $paths->page_id . '\' AND namespace=\'' . $paths->namespace . '\'');
  1359     if(!$e) jsdie('Error selecting category information for current page: '.$db->get_error());
  1359 		if(!$e) jsdie('Error selecting category information for current page: '.$db->get_error());
  1360     $cat_current = Array();
  1360 		$cat_current = Array();
  1361     while($r = $db->fetchrow())
  1361 		while($r = $db->fetchrow())
  1362     {
  1362 		{
  1363       $cat_current[] = $r;
  1363 			$cat_current[] = $r;
  1364     }
  1364 		}
  1365     $db->free_result();
  1365 		$db->free_result();
  1366     
  1366 		
  1367     $cat_all = array();
  1367 		$cat_all = array();
  1368     $q = $db->sql_query('SELECT * FROM ' . table_prefix . 'pages WHERE namespace = \'Category\';');
  1368 		$q = $db->sql_query('SELECT * FROM ' . table_prefix . 'pages WHERE namespace = \'Category\';');
  1369     if ( !$q )
  1369 		if ( !$q )
  1370       $db->_die();
  1370 			$db->_die();
  1371     
  1371 		
  1372     while ( $row = $db->fetchrow() )
  1372 		while ( $row = $db->fetchrow() )
  1373     {
  1373 		{
  1374       $cat_all[] = Namespace_Default::bake_cdata($row);
  1374 			$cat_all[] = Namespace_Default::bake_cdata($row);
  1375     }
  1375 		}
  1376     
  1376 		
  1377     // Make $cat_all an associative array, like $paths->pages
  1377 		// Make $cat_all an associative array, like $paths->pages
  1378     $sz = sizeof($cat_all);
  1378 		$sz = sizeof($cat_all);
  1379     for($i=0;$i<$sz;$i++)
  1379 		for($i=0;$i<$sz;$i++)
  1380     {
  1380 		{
  1381       $cat_all[$cat_all[$i]['urlname_nons']] = $cat_all[$i];
  1381 			$cat_all[$cat_all[$i]['urlname_nons']] = $cat_all[$i];
  1382     }
  1382 		}
  1383     // Now, the "zipper" function - join the list of categories with the list of cats that this page is a part of
  1383 		// Now, the "zipper" function - join the list of categories with the list of cats that this page is a part of
  1384     $cat_info = $cat_all;
  1384 		$cat_info = $cat_all;
  1385     for($i=0;$i<sizeof($cat_current);$i++)
  1385 		for($i=0;$i<sizeof($cat_current);$i++)
  1386     {
  1386 		{
  1387       $un = $cat_current[$i]['category_id'];
  1387 			$un = $cat_current[$i]['category_id'];
  1388       $cat_info[$un]['member'] = true;
  1388 			$cat_info[$un]['member'] = true;
  1389     }
  1389 		}
  1390     // Now copy the information we just set into the numerically named keys
  1390 		// Now copy the information we just set into the numerically named keys
  1391     for($i=0;$i<sizeof($cat_info)/2;$i++)
  1391 		for($i=0;$i<sizeof($cat_info)/2;$i++)
  1392     {
  1392 		{
  1393       $un = $cat_info[$i]['urlname_nons'];
  1393 			$un = $cat_info[$i]['urlname_nons'];
  1394       $cat_info[$i] = $cat_info[$un];
  1394 			$cat_info[$i] = $cat_info[$un];
  1395     }
  1395 		}
  1396     
  1396 		
  1397     echo 'catlist = new Array();'; // Initialize the client-side category list
  1397 		echo 'catlist = new Array();'; // Initialize the client-side category list
  1398     $_ob .= '<h3>' . $lang->get('catedit_title') . '</h3>
  1398 		$_ob .= '<h3>' . $lang->get('catedit_title') . '</h3>
  1399              <form name="mdgCatForm" action="'.makeUrlNS($namespace, $page_id, 'do=catedit').'" method="post">';
  1399  						<form name="mdgCatForm" action="'.makeUrlNS($namespace, $page_id, 'do=catedit').'" method="post">';
  1400     if ( sizeof($cat_info) < 1 )
  1400 		if ( sizeof($cat_info) < 1 )
  1401     {
  1401 		{
  1402       $_ob .= '<p>' . $lang->get('catedit_no_categories') . '</p>';
  1402 			$_ob .= '<p>' . $lang->get('catedit_no_categories') . '</p>';
  1403     }
  1403 		}
  1404     for ( $i = 0; $i < sizeof($cat_info) / 2; $i++ )
  1404 		for ( $i = 0; $i < sizeof($cat_info) / 2; $i++ )
  1405     {
  1405 		{
  1406       // Protection code added 1/3/07
  1406 			// Protection code added 1/3/07
  1407       // Updated 3/4/07
  1407 			// Updated 3/4/07
  1408       $is_prot = false;
  1408 			$is_prot = false;
  1409       $perms = $session->fetch_page_acl($cat_info[$i]['urlname_nons'], 'Category');
  1409 			$perms = $session->fetch_page_acl($cat_info[$i]['urlname_nons'], 'Category');
  1410       if ( !$session->get_permissions('edit_cat') || !$perms->get_permissions('edit_cat') ||
  1410 			if ( !$session->get_permissions('edit_cat') || !$perms->get_permissions('edit_cat') ||
  1411          ( $cat_info[$i]['really_protected'] && !$perms->get_permissions('even_when_protected') ) )
  1411  				( $cat_info[$i]['really_protected'] && !$perms->get_permissions('even_when_protected') ) )
  1412          $is_prot = true;
  1412  				$is_prot = true;
  1413       $prot = ( $is_prot ) ? ' disabled="disabled" ' : '';
  1413 			$prot = ( $is_prot ) ? ' disabled="disabled" ' : '';
  1414       $prottext = ( $is_prot ) ? ' <img alt="(protected)" width="16" height="16" src="'.scriptPath.'/images/lock16.png" />' : '';
  1414 			$prottext = ( $is_prot ) ? ' <img alt="(protected)" width="16" height="16" src="'.scriptPath.'/images/lock16.png" />' : '';
  1415       echo 'catlist[' . $i . '] = \'' . $cat_info[$i]['urlname_nons'] . '\';';
  1415 			echo 'catlist[' . $i . '] = \'' . $cat_info[$i]['urlname_nons'] . '\';';
  1416       $_ob .= '<span class="catCheck"><input ' . $prot . ' name="' . $cat_info[$i]['urlname_nons'] . '" id="mdgCat_' . $cat_info[$i]['urlname_nons'] . '" type="checkbox"';
  1416 			$_ob .= '<span class="catCheck"><input ' . $prot . ' name="' . $cat_info[$i]['urlname_nons'] . '" id="mdgCat_' . $cat_info[$i]['urlname_nons'] . '" type="checkbox"';
  1417       if(isset($cat_info[$i]['member'])) $_ob .= ' checked="checked"';
  1417 			if(isset($cat_info[$i]['member'])) $_ob .= ' checked="checked"';
  1418       $_ob .= '/>  <label for="mdgCat_' . $cat_info[$i]['urlname_nons'] . '">' . $cat_info[$i]['name'].$prottext.'</label></span><br />';
  1418 			$_ob .= '/>  <label for="mdgCat_' . $cat_info[$i]['urlname_nons'] . '">' . $cat_info[$i]['name'].$prottext.'</label></span><br />';
  1419     }
  1419 		}
  1420     
  1420 		
  1421     $disabled = ( sizeof($cat_info) < 1 ) ? 'disabled="disabled"' : '';
  1421 		$disabled = ( sizeof($cat_info) < 1 ) ? 'disabled="disabled"' : '';
  1422       
  1422 			
  1423     $_ob .= '<div style="border-top: 1px solid #CCC; padding-top: 5px; margin-top: 10px;"><input name="__enanoSaveButton" ' . $disabled . ' style="font-weight: bold;" type="submit" onclick="ajaxCatSave(); return false;" value="' . $lang->get('etc_save_changes') . '" /> <input name="__enanoCatCancel" type="submit" onclick="ajaxReset(); return false;" value="' . $lang->get('etc_cancel') . '" /></div></form>';
  1423 		$_ob .= '<div style="border-top: 1px solid #CCC; padding-top: 5px; margin-top: 10px;"><input name="__enanoSaveButton" ' . $disabled . ' style="font-weight: bold;" type="submit" onclick="ajaxCatSave(); return false;" value="' . $lang->get('etc_save_changes') . '" /> <input name="__enanoCatCancel" type="submit" onclick="ajaxReset(); return false;" value="' . $lang->get('etc_cancel') . '" /></div></form>';
  1424     
  1424 		
  1425     $cont = ob_get_contents();
  1425 		$cont = ob_get_contents();
  1426     ob_end_clean();
  1426 		ob_end_clean();
  1427     return Array($cont, $_ob);
  1427 		return Array($cont, $_ob);
  1428   }
  1428 	}
  1429   
  1429 	
  1430   /**
  1430 	/**
  1431    * Saves category information
  1431  	* Saves category information
  1432    * WARNING: If $which_cats is empty, all the category information for the selected page will be nuked!
  1432  	* WARNING: If $which_cats is empty, all the category information for the selected page will be nuked!
  1433    * @param $page_id string the page ID
  1433  	* @param $page_id string the page ID
  1434    * @param $namespace string the namespace
  1434  	* @param $namespace string the namespace
  1435    * @param $which_cats array associative array of categories to put the page in
  1435  	* @param $which_cats array associative array of categories to put the page in
  1436    * @return string "GOOD" on success, error string on failure
  1436  	* @return string "GOOD" on success, error string on failure
  1437    */
  1437  	*/
  1438   
  1438 	
  1439   public static function catsave($page_id, $namespace, $which_cats)
  1439 	public static function catsave($page_id, $namespace, $which_cats)
  1440   {
  1440 	{
  1441     global $db, $session, $paths, $template, $plugins; // Common objects
  1441 		global $db, $session, $paths, $template, $plugins; // Common objects
  1442     if(!$session->get_permissions('edit_cat')) return('Insufficient privileges to change category information');
  1442 		if(!$session->get_permissions('edit_cat')) return('Insufficient privileges to change category information');
  1443     
  1443 		
  1444     $page_perms = $session->fetch_page_acl($page_id, $namespace);
  1444 		$page_perms = $session->fetch_page_acl($page_id, $namespace);
  1445     $ns = namespace_factory($page_id, $namespace);
  1445 		$ns = namespace_factory($page_id, $namespace);
  1446     $page_data = $ns->get_cdata();
  1446 		$page_data = $ns->get_cdata();
  1447     
  1447 		
  1448     $cat_all = array();
  1448 		$cat_all = array();
  1449     $q = $db->sql_query('SELECT * FROM ' . table_prefix . 'pages WHERE namespace = \'Category\';');
  1449 		$q = $db->sql_query('SELECT * FROM ' . table_prefix . 'pages WHERE namespace = \'Category\';');
  1450     if ( !$q )
  1450 		if ( !$q )
  1451       $db->_die();
  1451 			$db->_die();
  1452     
  1452 		
  1453     while ( $row = $db->fetchrow() )
  1453 		while ( $row = $db->fetchrow() )
  1454     {
  1454 		{
  1455       $cat_all[] = Namespace_Default::bake_cdata($row);
  1455 			$cat_all[] = Namespace_Default::bake_cdata($row);
  1456     }
  1456 		}
  1457     
  1457 		
  1458     // Make $cat_all an associative array, like $paths->pages
  1458 		// Make $cat_all an associative array, like $paths->pages
  1459     $sz = sizeof($cat_all);
  1459 		$sz = sizeof($cat_all);
  1460     for($i=0;$i<$sz;$i++)
  1460 		for($i=0;$i<$sz;$i++)
  1461     {
  1461 		{
  1462       $cat_all[$cat_all[$i]['urlname_nons']] = $cat_all[$i];
  1462 			$cat_all[$cat_all[$i]['urlname_nons']] = $cat_all[$i];
  1463     }
  1463 		}
  1464     
  1464 		
  1465     $rowlist = Array();
  1465 		$rowlist = Array();
  1466     
  1466 		
  1467     for($i=0;$i<sizeof($cat_all)/2;$i++)
  1467 		for($i=0;$i<sizeof($cat_all)/2;$i++)
  1468     {
  1468 		{
  1469       $auth = true;
  1469 			$auth = true;
  1470       $perms = $session->fetch_page_acl($cat_all[$i]['urlname_nons'], 'Category');
  1470 			$perms = $session->fetch_page_acl($cat_all[$i]['urlname_nons'], 'Category');
  1471       if ( !$session->get_permissions('edit_cat') || !$perms->get_permissions('edit_cat') ||
  1471 			if ( !$session->get_permissions('edit_cat') || !$perms->get_permissions('edit_cat') ||
  1472          ( $cat_all[$i]['really_protected'] && !$perms->get_permissions('even_when_protected') ) ||
  1472  				( $cat_all[$i]['really_protected'] && !$perms->get_permissions('even_when_protected') ) ||
  1473          ( !$page_perms->get_permissions('even_when_protected') && $page_data['protected'] == '1' ) )
  1473  				( !$page_perms->get_permissions('even_when_protected') && $page_data['protected'] == '1' ) )
  1474          $auth = false;
  1474  				$auth = false;
  1475       if(!$auth)
  1475 			if(!$auth)
  1476       {
  1476 			{
  1477         // Find out if the page is currently in the category
  1477 				// Find out if the page is currently in the category
  1478         $q = $db->sql_query('SELECT * FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1478 				$q = $db->sql_query('SELECT * FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1479         if(!$q)
  1479 				if(!$q)
  1480           return 'MySQL error: ' . $db->get_error();
  1480 					return 'MySQL error: ' . $db->get_error();
  1481         if($db->numrows() > 0)
  1481 				if($db->numrows() > 0)
  1482         {
  1482 				{
  1483           $auth = true;
  1483 					$auth = true;
  1484           $which_cats[$cat_all[$i]['urlname_nons']] = true; // Force the category to stay in its current state
  1484 					$which_cats[$cat_all[$i]['urlname_nons']] = true; // Force the category to stay in its current state
  1485         }
  1485 				}
  1486         $db->free_result();
  1486 				$db->free_result();
  1487       }
  1487 			}
  1488       if(isset($which_cats[$cat_all[$i]['urlname_nons']]) && $which_cats[$cat_all[$i]['urlname_nons']] == true /* for clarity ;-) */ && $auth ) $rowlist[] = '(\'' . $page_id . '\', \'' . $namespace . '\', \'' . $cat_all[$i]['urlname_nons'] . '\')';
  1488 			if(isset($which_cats[$cat_all[$i]['urlname_nons']]) && $which_cats[$cat_all[$i]['urlname_nons']] == true /* for clarity ;-) */ && $auth ) $rowlist[] = '(\'' . $page_id . '\', \'' . $namespace . '\', \'' . $cat_all[$i]['urlname_nons'] . '\')';
  1489     }
  1489 		}
  1490     if(sizeof($rowlist) > 0)
  1490 		if(sizeof($rowlist) > 0)
  1491     {
  1491 		{
  1492       $val = implode(',', $rowlist);
  1492 			$val = implode(',', $rowlist);
  1493       $q = 'INSERT INTO ' . table_prefix.'categories(page_id,namespace,category_id) VALUES' . $val . ';';
  1493 			$q = 'INSERT INTO ' . table_prefix.'categories(page_id,namespace,category_id) VALUES' . $val . ';';
  1494       $e = $db->sql_query('DELETE FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1494 			$e = $db->sql_query('DELETE FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1495       if(!$e) $db->_die('The old category data could not be deleted.');
  1495 			if(!$e) $db->_die('The old category data could not be deleted.');
  1496       $e = $db->sql_query($q);
  1496 			$e = $db->sql_query($q);
  1497       if(!$e) $db->_die('The new category data could not be inserted.');
  1497 			if(!$e) $db->_die('The new category data could not be inserted.');
  1498       return('GOOD');
  1498 			return('GOOD');
  1499     }
  1499 		}
  1500     else
  1500 		else
  1501     {
  1501 		{
  1502       $e = $db->sql_query('DELETE FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1502 			$e = $db->sql_query('DELETE FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1503       if(!$e) $db->_die('The old category data could not be deleted.');
  1503 			if(!$e) $db->_die('The old category data could not be deleted.');
  1504       return('GOOD');
  1504 			return('GOOD');
  1505     }
  1505 		}
  1506   }
  1506 	}
  1507   
  1507 	
  1508   /**
  1508 	/**
  1509    * Sets the wiki mode level for a page.
  1509  	* Sets the wiki mode level for a page.
  1510    * @param $page_id string the page ID
  1510  	* @param $page_id string the page ID
  1511    * @param $namespace string the namespace
  1511  	* @param $namespace string the namespace
  1512    * @param $level int 0 for off, 1 for on, 2 for use global setting
  1512  	* @param $level int 0 for off, 1 for on, 2 for use global setting
  1513    * @return string "GOOD" on success, error string on failure
  1513  	* @return string "GOOD" on success, error string on failure
  1514    */
  1514  	*/
  1515   
  1515 	
  1516   public static function setwikimode($page_id, $namespace, $level)
  1516 	public static function setwikimode($page_id, $namespace, $level)
  1517   {
  1517 	{
  1518     global $db, $session, $paths, $template, $plugins; // Common objects
  1518 		global $db, $session, $paths, $template, $plugins; // Common objects
  1519     global $cache;
  1519 		global $cache;
  1520     
  1520 		
  1521     if(!$session->get_permissions('set_wiki_mode')) return('Insufficient access rights');
  1521 		if(!$session->get_permissions('set_wiki_mode')) return('Insufficient access rights');
  1522     if ( !isset($level) || ( isset($level) && !preg_match('#^([0-2]){1}$#', (string)$level) ) )
  1522 		if ( !isset($level) || ( isset($level) && !preg_match('#^([0-2]){1}$#', (string)$level) ) )
  1523     {
  1523 		{
  1524       return('Invalid mode string');
  1524 			return('Invalid mode string');
  1525     }
  1525 		}
  1526     $q = $db->sql_query('UPDATE ' . table_prefix.'pages SET wiki_mode=' . $level . ' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1526 		$q = $db->sql_query('UPDATE ' . table_prefix.'pages SET wiki_mode=' . $level . ' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1527     if ( !$q )
  1527 		if ( !$q )
  1528     {
  1528 		{
  1529       return('Error during update query: '.$db->get_error()."\n\nSQL Backtrace:\n".$db->sql_backtrace());
  1529 			return('Error during update query: '.$db->get_error()."\n\nSQL Backtrace:\n".$db->sql_backtrace());
  1530     }
  1530 		}
  1531     
  1531 		
  1532     $cache->purge('page_meta');
  1532 		$cache->purge('page_meta');
  1533     return('GOOD');
  1533 		return('GOOD');
  1534   }
  1534 	}
  1535   
  1535 	
  1536   /**
  1536 	/**
  1537    * Sets the access password for a page.
  1537  	* Sets the access password for a page.
  1538    * @param $page_id string the page ID
  1538  	* @param $page_id string the page ID
  1539    * @param $namespace string the namespace
  1539  	* @param $namespace string the namespace
  1540    * @param $pass string the SHA1 hash of the password - if the password doesn't match the regex ^([0-9a-f]*){40,40}$ it will be sha1'ed
  1540  	* @param $pass string the SHA1 hash of the password - if the password doesn't match the regex ^([0-9a-f]*){40,40}$ it will be sha1'ed
  1541    * @return string
  1541  	* @return string
  1542    */
  1542  	*/
  1543   
  1543 	
  1544   public static function setpass($page_id, $namespace, $pass)
  1544 	public static function setpass($page_id, $namespace, $pass)
  1545   {
  1545 	{
  1546     global $db, $session, $paths, $template, $plugins; // Common objects
  1546 		global $db, $session, $paths, $template, $plugins; // Common objects
  1547     global $lang, $cache;
  1547 		global $lang, $cache;
  1548     // Determine permissions
  1548 		// Determine permissions
  1549     $ns = namespace_factory($page_id, $namespace);
  1549 		$ns = namespace_factory($page_id, $namespace);
  1550     $cdata = $ns->get_cdata();
  1550 		$cdata = $ns->get_cdata();
  1551     if ( $cdata['password'] != '' )
  1551 		if ( $cdata['password'] != '' )
  1552       $a = $session->get_permissions('password_reset');
  1552 			$a = $session->get_permissions('password_reset');
  1553     else
  1553 		else
  1554       $a = $session->get_permissions('password_set');
  1554 			$a = $session->get_permissions('password_set');
  1555     if ( !$a )
  1555 		if ( !$a )
  1556       return $lang->get('etc_access_denied');
  1556 			return $lang->get('etc_access_denied');
  1557     if ( !isset($pass) )
  1557 		if ( !isset($pass) )
  1558       return('Password was not set on URL');
  1558 			return('Password was not set on URL');
  1559     $p = $pass;
  1559 		$p = $pass;
  1560     if ( !preg_match('#([0-9a-f]){40,40}#', $p) )
  1560 		if ( !preg_match('#([0-9a-f]){40,40}#', $p) )
  1561     {
  1561 		{
  1562       $p = sha1($p);
  1562 			$p = sha1($p);
  1563     }
  1563 		}
  1564     if ( $p == 'da39a3ee5e6b4b0d3255bfef95601890afd80709' )
  1564 		if ( $p == 'da39a3ee5e6b4b0d3255bfef95601890afd80709' )
  1565       // sha1('') = da39a3ee5e6b4b0d3255bfef95601890afd80709
  1565 			// sha1('') = da39a3ee5e6b4b0d3255bfef95601890afd80709
  1566       $p = '';
  1566 			$p = '';
  1567     $e = $db->sql_query('UPDATE ' . table_prefix.'pages SET password=\'' . $p . '\' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1567 		$e = $db->sql_query('UPDATE ' . table_prefix.'pages SET password=\'' . $p . '\' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
  1568     if ( !$e )
  1568 		if ( !$e )
  1569     {
  1569 		{
  1570       die('PageUtils::setpass(): Error during update query: '.$db->get_error()."\n\nSQL Backtrace:\n".$db->sql_backtrace());
  1570 			die('PageUtils::setpass(): Error during update query: '.$db->get_error()."\n\nSQL Backtrace:\n".$db->sql_backtrace());
  1571     }
  1571 		}
  1572     // Is the new password blank?
  1572 		// Is the new password blank?
  1573     if ( $p == '' )
  1573 		if ( $p == '' )
  1574     {
  1574 		{
  1575       return $lang->get('ajax_password_disable_success');
  1575 			return $lang->get('ajax_password_disable_success');
  1576     }
  1576 		}
  1577     else
  1577 		else
  1578     {
  1578 		{
  1579       return $lang->get('ajax_password_success');
  1579 			return $lang->get('ajax_password_success');
  1580     }
  1580 		}
  1581   }
  1581 	}
  1582   
  1582 	
  1583   /**
  1583 	/**
  1584    * Generates some preview HTML
  1584  	* Generates some preview HTML
  1585    * @param $text string the wikitext to use
  1585  	* @param $text string the wikitext to use
  1586    * @return string
  1586  	* @return string
  1587    */
  1587  	*/
  1588    
  1588  	
  1589   public static function genPreview($text)
  1589 	public static function genPreview($text)
  1590   {
  1590 	{
  1591     global $lang;
  1591 		global $lang;
  1592     $ret = '<div class="info-box">' . $lang->get('editor_preview_blurb') . '</div><div style="background-color: #F8F8F8; padding: 10px; border: 1px dashed #406080; max-height: 250px; overflow: auto; margin: 10px 0;">';
  1592 		$ret = '<div class="info-box">' . $lang->get('editor_preview_blurb') . '</div><div style="background-color: #F8F8F8; padding: 10px; border: 1px dashed #406080; max-height: 250px; overflow: auto; margin: 10px 0;">';
  1593     $text = RenderMan::render(RenderMan::preprocess_text($text, false, false));
  1593 		$text = RenderMan::render(RenderMan::preprocess_text($text, false, false));
  1594     ob_start();
  1594 		ob_start();
  1595     eval('?>' . $text);
  1595 		eval('?>' . $text);
  1596     $text = ob_get_contents();
  1596 		$text = ob_get_contents();
  1597     ob_end_clean();
  1597 		ob_end_clean();
  1598     $ret .= $text;
  1598 		$ret .= $text;
  1599     $ret .= '</div>';
  1599 		$ret .= '</div>';
  1600     return $ret;
  1600 		return $ret;
  1601   }
  1601 	}
  1602   
  1602 	
  1603   /**
  1603 	/**
  1604    * Makes a scrollable box
  1604  	* Makes a scrollable box
  1605    * @param string $text the inner HTML
  1605  	* @param string $text the inner HTML
  1606    * @param int $height Optional - the maximum height. Defaults to 250.
  1606  	* @param int $height Optional - the maximum height. Defaults to 250.
  1607    * @return string
  1607  	* @return string
  1608    */
  1608  	*/
  1609    
  1609  	
  1610   public static function scrollBox($text, $height = 250)
  1610 	public static function scrollBox($text, $height = 250)
  1611   {
  1611 	{
  1612     return '<div style="background-color: #F8F8F8; padding: 10px; border: 1px dashed #406080; max-height: '.(string)intval($height).'px; overflow: auto; margin: 1em 0 1em 1em;">' . $text . '</div>';
  1612 		return '<div style="background-color: #F8F8F8; padding: 10px; border: 1px dashed #406080; max-height: '.(string)intval($height).'px; overflow: auto; margin: 1em 0 1em 1em;">' . $text . '</div>';
  1613   }
  1613 	}
  1614   
  1614 	
  1615   /**
  1615 	/**
  1616    * Generates a diff summary between two page revisions.
  1616  	* Generates a diff summary between two page revisions.
  1617    * @param $page_id the page ID
  1617  	* @param $page_id the page ID
  1618    * @param $namespace the namespace
  1618  	* @param $namespace the namespace
  1619    * @param $id1 the time ID of the first revision
  1619  	* @param $id1 the time ID of the first revision
  1620    * @param $id2 the time ID of the second revision
  1620  	* @param $id2 the time ID of the second revision
  1621    * @return string XHTML-formatted diff
  1621  	* @return string XHTML-formatted diff
  1622    */
  1622  	*/
  1623    
  1623  	
  1624   public static function pagediff($page_id, $namespace, $id1, $id2)
  1624 	public static function pagediff($page_id, $namespace, $id1, $id2)
  1625   {
  1625 	{
  1626     global $db, $session, $paths, $template, $plugins; // Common objects
  1626 		global $db, $session, $paths, $template, $plugins; // Common objects
  1627     global $lang;
  1627 		global $lang;
  1628     
  1628 		
  1629     if ( !$session->get_permissions('history_view') )
  1629 		if ( !$session->get_permissions('history_view') )
  1630       return $lang->get('etc_access_denied');
  1630 			return $lang->get('etc_access_denied');
  1631     
  1631 		
  1632     if(!preg_match('#^([0-9]+)$#', (string)$id1) ||
  1632 		if(!preg_match('#^([0-9]+)$#', (string)$id1) ||
  1633        !preg_match('#^([0-9]+)$#', (string)$id2  )) return 'SQL injection attempt';
  1633  			!preg_match('#^([0-9]+)$#', (string)$id2  )) return 'SQL injection attempt';
  1634     // OK we made it through security
  1634 		// OK we made it through security
  1635     // Safest way to make sure we don't end up with the revisions in wrong columns is to make 2 queries
  1635 		// Safest way to make sure we don't end up with the revisions in wrong columns is to make 2 queries
  1636     if ( !$q1 = $db->sql_query('SELECT time_id,page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE log_id = ' . $id1 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: ' . $db->get_error();
  1636 		if ( !$q1 = $db->sql_query('SELECT time_id,page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE log_id = ' . $id1 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: ' . $db->get_error();
  1637     if ( !$q2 = $db->sql_query('SELECT time_id,page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE log_id = ' . $id2 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: ' . $db->get_error();
  1637 		if ( !$q2 = $db->sql_query('SELECT time_id,page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE log_id = ' . $id2 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: ' . $db->get_error();
  1638     $row1 = $db->fetchrow($q1);
  1638 		$row1 = $db->fetchrow($q1);
  1639     $db->free_result($q1);
  1639 		$db->free_result($q1);
  1640     $row2 = $db->fetchrow($q2);
  1640 		$row2 = $db->fetchrow($q2);
  1641     $db->free_result($q2);
  1641 		$db->free_result($q2);
  1642     if(sizeof($row1) < 1 || sizeof($row2) < 2)
  1642 		if(sizeof($row1) < 1 || sizeof($row2) < 2)
  1643     {
  1643 		{
  1644       if ( !$q1 = $db->sql_query('SELECT time_id,page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE time_id = ' . $id1 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: ' . $db->get_error();
  1644 			if ( !$q1 = $db->sql_query('SELECT time_id,page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE time_id = ' . $id1 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: ' . $db->get_error();
  1645       if ( !$q2 = $db->sql_query('SELECT time_id,page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE time_id = ' . $id2 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: ' . $db->get_error();
  1645 			if ( !$q2 = $db->sql_query('SELECT time_id,page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE time_id = ' . $id2 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: ' . $db->get_error();
  1646       $row1 = $db->fetchrow($q1);
  1646 			$row1 = $db->fetchrow($q1);
  1647       $db->free_result($q1);
  1647 			$db->free_result($q1);
  1648       $row2 = $db->fetchrow($q2);
  1648 			$row2 = $db->fetchrow($q2);
  1649       $db->free_result($q2);
  1649 			$db->free_result($q2);
  1650       if(sizeof($row1) < 1 || sizeof($row2) < 2)
  1650 			if(sizeof($row1) < 1 || sizeof($row2) < 2)
  1651         return 'Couldn\'t find any rows that matched the query. The time ID probably doesn\'t exist in the logs table.';
  1651 				return 'Couldn\'t find any rows that matched the query. The time ID probably doesn\'t exist in the logs table.';
  1652     }
  1652 		}
  1653     $text1 = $row1['page_text'];
  1653 		$text1 = $row1['page_text'];
  1654     $text2 = $row2['page_text'];
  1654 		$text2 = $row2['page_text'];
  1655     $time1 = enano_date(ED_DATE | ED_TIME, $row1['time_id']);
  1655 		$time1 = enano_date(ED_DATE | ED_TIME, $row1['time_id']);
  1656     $time2 = enano_date(ED_DATE | ED_TIME, $row2['time_id']);
  1656 		$time2 = enano_date(ED_DATE | ED_TIME, $row2['time_id']);
  1657     $_ob = "
  1657 		$_ob = "
  1658     <p>" . $lang->get('history_lbl_comparingrevisions') . " {$time1} &rarr; {$time2}</p>
  1658 		<p>" . $lang->get('history_lbl_comparingrevisions') . " {$time1} &rarr; {$time2}</p>
  1659     ";
  1659 		";
  1660     // Free some memory
  1660 		// Free some memory
  1661     unset($row1, $row2, $q1, $q2);
  1661 		unset($row1, $row2, $q1, $q2);
  1662     
  1662 		
  1663     $_ob .= RenderMan::diff($text1, $text2);
  1663 		$_ob .= RenderMan::diff($text1, $text2);
  1664     return $_ob;
  1664 		return $_ob;
  1665   }
  1665 	}
  1666   
  1666 	
  1667   /**
  1667 	/**
  1668    * Gets ACL information about the selected page for target type X and target ID Y.
  1668  	* Gets ACL information about the selected page for target type X and target ID Y.
  1669    * @param array $parms What to select. This is an array purely for JSON compatibility. It should be an associative array with keys target_type and target_id.
  1669  	* @param array $parms What to select. This is an array purely for JSON compatibility. It should be an associative array with keys target_type and target_id.
  1670    * @return array
  1670  	* @return array
  1671    */
  1671  	*/
  1672    
  1672  	
  1673   public static function acl_editor($parms = Array())
  1673 	public static function acl_editor($parms = Array())
  1674   {
  1674 	{
  1675     global $db, $session, $paths, $template, $plugins; // Common objects
  1675 		global $db, $session, $paths, $template, $plugins; // Common objects
  1676     global $lang;
  1676 		global $lang;
  1677     
  1677 		
  1678     if(!$session->get_permissions('edit_acl') && ( $session->user_level < USER_LEVEL_ADMIN || !defined('ACL_ALWAYS_ALLOW_ADMIN_EDIT_ACL')) )
  1678 		if(!$session->get_permissions('edit_acl') && ( $session->user_level < USER_LEVEL_ADMIN || !defined('ACL_ALWAYS_ALLOW_ADMIN_EDIT_ACL')) )
  1679     {
  1679 		{
  1680       return Array(
  1680 			return Array(
  1681         'mode' => 'error',
  1681 				'mode' => 'error',
  1682         'error' => $lang->get('acl_err_access_denied')
  1682 				'error' => $lang->get('acl_err_access_denied')
  1683         );
  1683 				);
  1684     }
  1684 		}
  1685     if ( !$session->sid_super )
  1685 		if ( !$session->sid_super )
  1686     {
  1686 		{
  1687       return Array(
  1687 			return Array(
  1688         'mode' => 'error',
  1688 				'mode' => 'error',
  1689         'error' => $lang->get('etc_access_denied_need_reauth')
  1689 				'error' => $lang->get('etc_access_denied_need_reauth')
  1690         );
  1690 				);
  1691     }
  1691 		}
  1692     $parms['page_id'] = ( isset($parms['page_id']) ) ? $parms['page_id'] : false;
  1692 		$parms['page_id'] = ( isset($parms['page_id']) ) ? $parms['page_id'] : false;
  1693     $parms['namespace'] = ( isset($parms['namespace']) ) ? $parms['namespace'] : false;
  1693 		$parms['namespace'] = ( isset($parms['namespace']) ) ? $parms['namespace'] : false;
  1694     $page_id =& $parms['page_id'];
  1694 		$page_id =& $parms['page_id'];
  1695     $namespace =& $parms['namespace'];
  1695 		$namespace =& $parms['namespace'];
  1696     $page_where_clause      = ( empty($page_id) || empty($namespace) ) ? 'AND a.page_id IS NULL AND a.namespace IS NULL' : 'AND a.page_id=\'' . $db->escape($page_id) . '\' AND a.namespace=\'' . $db->escape($namespace) . '\'';
  1696 		$page_where_clause      = ( empty($page_id) || empty($namespace) ) ? 'AND a.page_id IS NULL AND a.namespace IS NULL' : 'AND a.page_id=\'' . $db->escape($page_id) . '\' AND a.namespace=\'' . $db->escape($namespace) . '\'';
  1697     $page_where_clause_lite = ( empty($page_id) || empty($namespace) ) ? 'AND page_id IS NULL AND namespace IS NULL' : 'AND page_id=\'' . $db->escape($page_id) . '\' AND namespace=\'' . $db->escape($namespace) . '\'';
  1697 		$page_where_clause_lite = ( empty($page_id) || empty($namespace) ) ? 'AND page_id IS NULL AND namespace IS NULL' : 'AND page_id=\'' . $db->escape($page_id) . '\' AND namespace=\'' . $db->escape($namespace) . '\'';
  1698     //die(print_r($page_id,true));
  1698 		//die(print_r($page_id,true));
  1699     $template->load_theme();
  1699 		$template->load_theme();
  1700     // $perms_obj = $session->fetch_page_acl($page_id, $namespace);
  1700 		// $perms_obj = $session->fetch_page_acl($page_id, $namespace);
  1701     $perms_obj =& $session;
  1701 		$perms_obj =& $session;
  1702     $return = Array();
  1702 		$return = Array();
  1703     if ( !file_exists(ENANO_ROOT . '/themes/' . $session->theme . '/acledit.tpl') )
  1703 		if ( !file_exists(ENANO_ROOT . '/themes/' . $session->theme . '/acledit.tpl') )
  1704     {
  1704 		{
  1705       return Array(
  1705 			return Array(
  1706         'mode' => 'error',
  1706 				'mode' => 'error',
  1707         'error' => $lang->get('acl_err_missing_template'),
  1707 				'error' => $lang->get('acl_err_missing_template'),
  1708       );
  1708 			);
  1709     }
  1709 		}
  1710     $return['template'] = $template->extract_vars('acledit.tpl');
  1710 		$return['template'] = $template->extract_vars('acledit.tpl');
  1711     $return['page_id'] = $page_id;
  1711 		$return['page_id'] = $page_id;
  1712     $return['namespace'] = $namespace;
  1712 		$return['namespace'] = $namespace;
  1713     if(isset($parms['mode']))
  1713 		if(isset($parms['mode']))
  1714     {
  1714 		{
  1715       switch($parms['mode'])
  1715 			switch($parms['mode'])
  1716       {
  1716 			{
  1717         case 'listgroups':
  1717 				case 'listgroups':
  1718           $return['groups'] = Array();
  1718 					$return['groups'] = Array();
  1719           $q = $db->sql_query('SELECT group_id,group_name FROM ' . table_prefix.'groups ORDER BY group_name ASC;');
  1719 					$q = $db->sql_query('SELECT group_id,group_name FROM ' . table_prefix.'groups ORDER BY group_name ASC;');
  1720           while($row = $db->fetchrow())
  1720 					while($row = $db->fetchrow())
  1721           {
  1721 					{
  1722             $return['groups'][] = Array(
  1722 						$return['groups'][] = Array(
  1723               'id' => $row['group_id'],
  1723 							'id' => $row['group_id'],
  1724               'name' => $row['group_name'],
  1724 							'name' => $row['group_name'],
  1725               );
  1725 							);
  1726           }
  1726 					}
  1727           $db->free_result();
  1727 					$db->free_result();
  1728           $return['page_groups'] = Array();
  1728 					$return['page_groups'] = Array();
  1729           $q = $db->sql_query('SELECT pg_id,pg_name FROM ' . table_prefix.'page_groups ORDER BY pg_name ASC;');
  1729 					$q = $db->sql_query('SELECT pg_id,pg_name FROM ' . table_prefix.'page_groups ORDER BY pg_name ASC;');
  1730           if ( !$q )
  1730 					if ( !$q )
  1731             return Array(
  1731 						return Array(
  1732               'mode' => 'error',
  1732 							'mode' => 'error',
  1733               'error' => $db->get_error()
  1733 							'error' => $db->get_error()
  1734               );
  1734 							);
  1735           while ( $row = $db->fetchrow() )
  1735 					while ( $row = $db->fetchrow() )
  1736           {
  1736 					{
  1737             $return['page_groups'][] = Array(
  1737 						$return['page_groups'][] = Array(
  1738                 'id' => $row['pg_id'],
  1738 								'id' => $row['pg_id'],
  1739                 'name' => $row['pg_name']
  1739 								'name' => $row['pg_name']
  1740               );
  1740 							);
  1741           }
  1741 					}
  1742           break;
  1742 					break;
  1743         case 'seltarget_id':
  1743 				case 'seltarget_id':
  1744           if ( !is_int($parms['target_id']) )
  1744 					if ( !is_int($parms['target_id']) )
  1745           {
  1745 					{
  1746             return Array(
  1746 						return Array(
  1747               'mode' => 'error',
  1747 							'mode' => 'error',
  1748               'error' => 'Expected parameter target_id type int'
  1748 							'error' => 'Expected parameter target_id type int'
  1749               );
  1749 							);
  1750           }
  1750 					}
  1751           $q = $db->sql_query('SELECT target_id, target_type, page_id, namespace, rules FROM ' . table_prefix . "acl WHERE rule_id = {$parms['target_id']};");
  1751 					$q = $db->sql_query('SELECT target_id, target_type, page_id, namespace, rules FROM ' . table_prefix . "acl WHERE rule_id = {$parms['target_id']};");
  1752           if ( !$q )
  1752 					if ( !$q )
  1753             return Array(
  1753 						return Array(
  1754               'mode' => 'error',
  1754 							'mode' => 'error',
  1755               'error' => $db->get_error()
  1755 							'error' => $db->get_error()
  1756               );
  1756 							);
  1757           if ( $db->numrows() < 1 )
  1757 					if ( $db->numrows() < 1 )
  1758             return Array(
  1758 						return Array(
  1759               'mode' => 'error',
  1759 							'mode' => 'error',
  1760               'error' => "No rule with ID {$parms['target_id']} found"
  1760 							'error' => "No rule with ID {$parms['target_id']} found"
  1761               );
  1761 							);
  1762             $parms = $db->fetchrow();
  1762 						$parms = $db->fetchrow();
  1763             $db->free_result();
  1763 						$db->free_result();
  1764             
  1764 						
  1765             // regenerate page selection
  1765 						// regenerate page selection
  1766             $parms['page_id'] = ( isset($parms['page_id']) ) ? $parms['page_id'] : false;
  1766 						$parms['page_id'] = ( isset($parms['page_id']) ) ? $parms['page_id'] : false;
  1767             $parms['namespace'] = ( isset($parms['namespace']) ) ? $parms['namespace'] : false;
  1767 						$parms['namespace'] = ( isset($parms['namespace']) ) ? $parms['namespace'] : false;
  1768             $parms['mode'] = 'seltarget_id';
  1768 						$parms['mode'] = 'seltarget_id';
  1769             $page_id =& $parms['page_id'];
  1769 						$page_id =& $parms['page_id'];
  1770             $namespace =& $parms['namespace'];
  1770 						$namespace =& $parms['namespace'];
  1771             $page_where_clause      = ( empty($page_id) || empty($namespace) ) ? 'AND a.page_id IS NULL AND a.namespace IS NULL' : 'AND a.page_id=\'' . $db->escape($page_id) . '\' AND a.namespace=\'' . $db->escape($namespace) . '\'';
  1771 						$page_where_clause      = ( empty($page_id) || empty($namespace) ) ? 'AND a.page_id IS NULL AND a.namespace IS NULL' : 'AND a.page_id=\'' . $db->escape($page_id) . '\' AND a.namespace=\'' . $db->escape($namespace) . '\'';
  1772             $page_where_clause_lite = ( empty($page_id) || empty($namespace) ) ? 'AND page_id IS NULL AND namespace IS NULL' : 'AND page_id=\'' . $db->escape($page_id) . '\' AND namespace=\'' . $db->escape($namespace) . '\'';
  1772 						$page_where_clause_lite = ( empty($page_id) || empty($namespace) ) ? 'AND page_id IS NULL AND namespace IS NULL' : 'AND page_id=\'' . $db->escape($page_id) . '\' AND namespace=\'' . $db->escape($namespace) . '\'';
  1773             
  1773 						
  1774             $return['page_id'] = $parms['page_id'];
  1774 						$return['page_id'] = $parms['page_id'];
  1775             $return['namespace'] = $parms['namespace'];
  1775 						$return['namespace'] = $parms['namespace'];
  1776             
  1776 						
  1777             // From here, let the seltarget handler take over
  1777 						// From here, let the seltarget handler take over
  1778         case 'seltarget':
  1778 				case 'seltarget':
  1779           $return['mode'] = 'seltarget';
  1779 					$return['mode'] = 'seltarget';
  1780           $return['acl_types'] = $perms_obj->acl_types;
  1780 					$return['acl_types'] = $perms_obj->acl_types;
  1781           $return['acl_deps'] = $perms_obj->acl_deps;
  1781 					$return['acl_deps'] = $perms_obj->acl_deps;
  1782           $return['acl_descs'] = $perms_obj->acl_descs;
  1782 					$return['acl_descs'] = $perms_obj->acl_descs;
  1783           $return['target_type'] = $parms['target_type'];
  1783 					$return['target_type'] = $parms['target_type'];
  1784           $return['target_id'] = $parms['target_id'];
  1784 					$return['target_id'] = $parms['target_id'];
  1785           switch($parms['target_type'])
  1785 					switch($parms['target_type'])
  1786           {
  1786 					{
  1787             case ACL_TYPE_USER:
  1787 						case ACL_TYPE_USER:
  1788               $user_col = ( $parms['mode'] == 'seltarget_id' ) ? 'user_id' : 'username';
  1788 							$user_col = ( $parms['mode'] == 'seltarget_id' ) ? 'user_id' : 'username';
  1789               $q = $db->sql_query('SELECT a.rules,u.user_id,u.username FROM ' . table_prefix.'users AS u
  1789 							$q = $db->sql_query('SELECT a.rules,u.user_id,u.username FROM ' . table_prefix.'users AS u
  1790                   LEFT JOIN ' . table_prefix.'acl AS a
  1790 									LEFT JOIN ' . table_prefix.'acl AS a
  1791                     ON a.target_id=u.user_id
  1791 										ON a.target_id=u.user_id
  1792                   WHERE a.target_type='.ACL_TYPE_USER.'
  1792 									WHERE a.target_type='.ACL_TYPE_USER.'
  1793                     AND u.' . $user_col . ' = \'' . $db->escape($parms['target_id']) . '\'
  1793 										AND u.' . $user_col . ' = \'' . $db->escape($parms['target_id']) . '\'
  1794                     ' . $page_where_clause . ';');
  1794 										' . $page_where_clause . ';');
  1795               if(!$q)
  1795 							if(!$q)
  1796                 return(Array('mode'=>'error','error'=>$db->get_error()));
  1796 								return(Array('mode'=>'error','error'=>$db->get_error()));
  1797               if($db->numrows() < 1)
  1797 							if($db->numrows() < 1)
  1798               {
  1798 							{
  1799                 $return['type'] = 'new';
  1799 								$return['type'] = 'new';
  1800                 $q = $db->sql_query('SELECT user_id,username FROM ' . table_prefix.'users WHERE username=\'' . $db->escape($parms['target_id']) . '\';');
  1800 								$q = $db->sql_query('SELECT user_id,username FROM ' . table_prefix.'users WHERE username=\'' . $db->escape($parms['target_id']) . '\';');
  1801                 if(!$q)
  1801 								if(!$q)
  1802                   return(Array('mode'=>'error','error'=>$db->get_error()));
  1802 									return(Array('mode'=>'error','error'=>$db->get_error()));
  1803                 if($db->numrows() < 1)
  1803 								if($db->numrows() < 1)
  1804                   return Array('mode'=>'error','error'=>$lang->get('acl_err_user_not_found'),'debug' => $db->sql_backtrace());
  1804 									return Array('mode'=>'error','error'=>$lang->get('acl_err_user_not_found'),'debug' => $db->sql_backtrace());
  1805                 $row = $db->fetchrow();
  1805 								$row = $db->fetchrow();
  1806                 $return['target_name'] = $row['username'];
  1806 								$return['target_name'] = $row['username'];
  1807                 $return['target_id'] = intval($row['user_id']);
  1807 								$return['target_id'] = intval($row['user_id']);
  1808                 $return['current_perms'] = array();
  1808 								$return['current_perms'] = array();
  1809               }
  1809 							}
  1810               else
  1810 							else
  1811               {
  1811 							{
  1812                 $return['type'] = 'edit';
  1812 								$return['type'] = 'edit';
  1813                 $row = $db->fetchrow();
  1813 								$row = $db->fetchrow();
  1814                 $return['target_name'] = $row['username'];
  1814 								$return['target_name'] = $row['username'];
  1815                 $return['target_id'] = intval($row['user_id']);
  1815 								$return['target_id'] = intval($row['user_id']);
  1816                 $return['current_perms'] = $session->string_to_perm($row['rules']);
  1816 								$return['current_perms'] = $session->string_to_perm($row['rules']);
  1817               }
  1817 							}
  1818               $db->free_result();
  1818 							$db->free_result();
  1819               // Eliminate types that don't apply to this namespace
  1819 							// Eliminate types that don't apply to this namespace
  1820               if ( $namespace && $namespace != '__PageGroup' )
  1820 							if ( $namespace && $namespace != '__PageGroup' )
  1821               {
  1821 							{
  1822                 foreach ( $return['current_perms'] AS $i => $perm )
  1822 								foreach ( $return['current_perms'] AS $i => $perm )
  1823                 {
  1823 								{
  1824                   if ( ( $page_id != null && $namespace != null ) && ( !in_array ( $namespace, $session->acl_scope[$i] ) && !in_array('All', $session->acl_scope[$i]) ) )
  1824 									if ( ( $page_id != null && $namespace != null ) && ( !in_array ( $namespace, $session->acl_scope[$i] ) && !in_array('All', $session->acl_scope[$i]) ) )
  1825                   {
  1825 									{
  1826                     // echo "// SCOPE CONTROL: eliminating: $i\n";
  1826 										// echo "// SCOPE CONTROL: eliminating: $i\n";
  1827                     unset($return['current_perms'][$i]);
  1827 										unset($return['current_perms'][$i]);
  1828                     unset($return['acl_types'][$i]);
  1828 										unset($return['acl_types'][$i]);
  1829                     unset($return['acl_descs'][$i]);
  1829 										unset($return['acl_descs'][$i]);
  1830                     unset($return['acl_deps'][$i]);
  1830 										unset($return['acl_deps'][$i]);
  1831                   }
  1831 									}
  1832                 }
  1832 								}
  1833               }
  1833 							}
  1834               break;
  1834 							break;
  1835             case ACL_TYPE_GROUP:
  1835 						case ACL_TYPE_GROUP:
  1836               $q = $db->sql_query('SELECT a.rules,g.group_name,g.group_id FROM ' . table_prefix.'groups AS g
  1836 							$q = $db->sql_query('SELECT a.rules,g.group_name,g.group_id FROM ' . table_prefix.'groups AS g
  1837                   LEFT JOIN ' . table_prefix.'acl AS a
  1837 									LEFT JOIN ' . table_prefix.'acl AS a
  1838                     ON a.target_id=g.group_id
  1838 										ON a.target_id=g.group_id
  1839                   WHERE a.target_type='.ACL_TYPE_GROUP.'
  1839 									WHERE a.target_type='.ACL_TYPE_GROUP.'
  1840                     AND g.group_id=\''.intval($parms['target_id']).'\'
  1840 										AND g.group_id=\''.intval($parms['target_id']).'\'
  1841                     ' . $page_where_clause . ';');
  1841 										' . $page_where_clause . ';');
  1842               if(!$q)
  1842 							if(!$q)
  1843                 return(Array('mode'=>'error','error'=>$db->get_error()));
  1843 								return(Array('mode'=>'error','error'=>$db->get_error()));
  1844               if($db->numrows() < 1)
  1844 							if($db->numrows() < 1)
  1845               {
  1845 							{
  1846                 $return['type'] = 'new';
  1846 								$return['type'] = 'new';
  1847                 $q = $db->sql_query('SELECT group_id,group_name FROM ' . table_prefix.'groups WHERE group_id=\''.intval($parms['target_id']).'\';');
  1847 								$q = $db->sql_query('SELECT group_id,group_name FROM ' . table_prefix.'groups WHERE group_id=\''.intval($parms['target_id']).'\';');
  1848                 if(!$q)
  1848 								if(!$q)
  1849                   return(Array('mode'=>'error','error'=>$db->get_error()));
  1849 									return(Array('mode'=>'error','error'=>$db->get_error()));
  1850                 if($db->numrows() < 1)
  1850 								if($db->numrows() < 1)
  1851                   return Array('mode'=>'error','error'=>$lang->get('acl_err_bad_group_id'));
  1851 									return Array('mode'=>'error','error'=>$lang->get('acl_err_bad_group_id'));
  1852                 $row = $db->fetchrow();
  1852 								$row = $db->fetchrow();
  1853                 $return['target_name'] = $row['group_name'];
  1853 								$return['target_name'] = $row['group_name'];
  1854                 $return['target_id'] = intval($row['group_id']);
  1854 								$return['target_id'] = intval($row['group_id']);
  1855                 $return['current_perms'] = array();
  1855 								$return['current_perms'] = array();
  1856               }
  1856 							}
  1857               else
  1857 							else
  1858               {
  1858 							{
  1859                 $return['type'] = 'edit';
  1859 								$return['type'] = 'edit';
  1860                 $row = $db->fetchrow();
  1860 								$row = $db->fetchrow();
  1861                 $return['target_name'] = $row['group_name'];
  1861 								$return['target_name'] = $row['group_name'];
  1862                 $return['target_id'] = intval($row['group_id']);
  1862 								$return['target_id'] = intval($row['group_id']);
  1863                 $return['current_perms'] = $session->string_to_perm($row['rules']);
  1863 								$return['current_perms'] = $session->string_to_perm($row['rules']);
  1864               }
  1864 							}
  1865               $db->free_result();
  1865 							$db->free_result();
  1866               // Eliminate types that don't apply to this namespace
  1866 							// Eliminate types that don't apply to this namespace
  1867               if ( $namespace && $namespace != '__PageGroup' )
  1867 							if ( $namespace && $namespace != '__PageGroup' )
  1868               {
  1868 							{
  1869                 foreach ( $return['current_perms'] AS $i => $perm )
  1869 								foreach ( $return['current_perms'] AS $i => $perm )
  1870                 {
  1870 								{
  1871                   if ( ( $page_id != false && $namespace != false ) && ( !in_array ( $namespace, $session->acl_scope[$i] ) && !in_array('All', $session->acl_scope[$i]) ) )
  1871 									if ( ( $page_id != false && $namespace != false ) && ( !in_array ( $namespace, $session->acl_scope[$i] ) && !in_array('All', $session->acl_scope[$i]) ) )
  1872                   {
  1872 									{
  1873                     // echo "// SCOPE CONTROL: eliminating: $i\n"; //; ".print_r($namespace,true).":".print_r($page_id,true)."\n";
  1873 										// echo "// SCOPE CONTROL: eliminating: $i\n"; //; ".print_r($namespace,true).":".print_r($page_id,true)."\n";
  1874                     unset($return['current_perms'][$i]);
  1874 										unset($return['current_perms'][$i]);
  1875                     unset($return['acl_types'][$i]);
  1875 										unset($return['acl_types'][$i]);
  1876                     unset($return['acl_descs'][$i]);
  1876 										unset($return['acl_descs'][$i]);
  1877                     unset($return['acl_deps'][$i]);
  1877 										unset($return['acl_deps'][$i]);
  1878                   }
  1878 									}
  1879                 }
  1879 								}
  1880               }
  1880 							}
  1881               //return Array('mode'=>'debug','text'=>print_r($return, true));
  1881 							//return Array('mode'=>'debug','text'=>print_r($return, true));
  1882               break;
  1882 							break;
  1883             default:
  1883 						default:
  1884               return Array('mode'=>'error','error','Invalid ACL type ID');
  1884 							return Array('mode'=>'error','error','Invalid ACL type ID');
  1885               break;
  1885 							break;
  1886           }
  1886 					}
  1887           return $return;
  1887 					return $return;
  1888           break;
  1888 					break;
  1889         case 'save_new':
  1889 				case 'save_new':
  1890         case 'save_edit':
  1890 				case 'save_edit':
  1891           if ( defined('ENANO_DEMO_MODE') )
  1891 					if ( defined('ENANO_DEMO_MODE') )
  1892           {
  1892 					{
  1893             return Array('mode'=>'error','error'=>$lang->get('acl_err_demo'));
  1893 						return Array('mode'=>'error','error'=>$lang->get('acl_err_demo'));
  1894           }
  1894 					}
  1895           $q = $db->sql_query('DELETE FROM ' . table_prefix.'acl WHERE target_type='.intval($parms['target_type']).' AND target_id='.intval($parms['target_id']).'
  1895 					$q = $db->sql_query('DELETE FROM ' . table_prefix.'acl WHERE target_type='.intval($parms['target_type']).' AND target_id='.intval($parms['target_id']).'
  1896             ' . $page_where_clause_lite . ';');
  1896 						' . $page_where_clause_lite . ';');
  1897           if(!$q)
  1897 					if(!$q)
  1898             return Array('mode'=>'error','error'=>$db->get_error());
  1898 						return Array('mode'=>'error','error'=>$db->get_error());
  1899           if ( sizeof ( $parms['perms'] ) < 1 )
  1899 					if ( sizeof ( $parms['perms'] ) < 1 )
  1900           {
  1900 					{
  1901             // As of 1.1.x, this returns success because the rule length is zero if the user selected "inherit" in all columns
  1901 						// As of 1.1.x, this returns success because the rule length is zero if the user selected "inherit" in all columns
  1902             return Array(
  1902 						return Array(
  1903               'mode' => 'success',
  1903 							'mode' => 'success',
  1904               'target_type' => $parms['target_type'],
  1904 							'target_type' => $parms['target_type'],
  1905               'target_id' => $parms['target_id'],
  1905 							'target_id' => $parms['target_id'],
  1906               'target_name' => $parms['target_name'],
  1906 							'target_name' => $parms['target_name'],
  1907               'page_id' => $page_id,
  1907 							'page_id' => $page_id,
  1908               'namespace' => $namespace,
  1908 							'namespace' => $namespace,
  1909             );
  1909 						);
  1910           }
  1910 					}
  1911           $rules = $session->perm_to_string($parms['perms']);
  1911 					$rules = $session->perm_to_string($parms['perms']);
  1912           $q = ($page_id && $namespace) ? 'INSERT INTO ' . table_prefix.'acl ( target_type, target_id, page_id, namespace, rules )
  1912 					$q = ($page_id && $namespace) ? 'INSERT INTO ' . table_prefix.'acl ( target_type, target_id, page_id, namespace, rules )
  1913                                              VALUES( '.intval($parms['target_type']).', '.intval($parms['target_id']).', \'' . $db->escape($page_id) . '\', \'' . $db->escape($namespace) . '\', \'' . $db->escape($rules) . '\' )' :
  1913  																						VALUES( '.intval($parms['target_type']).', '.intval($parms['target_id']).', \'' . $db->escape($page_id) . '\', \'' . $db->escape($namespace) . '\', \'' . $db->escape($rules) . '\' )' :
  1914                                           'INSERT INTO ' . table_prefix.'acl ( target_type, target_id, rules )
  1914 																					'INSERT INTO ' . table_prefix.'acl ( target_type, target_id, rules )
  1915                                              VALUES( '.intval($parms['target_type']).', '.intval($parms['target_id']).', \'' . $db->escape($rules) . '\' )';
  1915  																						VALUES( '.intval($parms['target_type']).', '.intval($parms['target_id']).', \'' . $db->escape($rules) . '\' )';
  1916           if(!$db->sql_query($q)) return Array('mode'=>'error','error'=>$db->get_error());
  1916 					if(!$db->sql_query($q)) return Array('mode'=>'error','error'=>$db->get_error());
  1917           return Array(
  1917 					return Array(
  1918               'mode' => 'success',
  1918 							'mode' => 'success',
  1919               'target_type' => $parms['target_type'],
  1919 							'target_type' => $parms['target_type'],
  1920               'target_id' => $parms['target_id'],
  1920 							'target_id' => $parms['target_id'],
  1921               'target_name' => $parms['target_name'],
  1921 							'target_name' => $parms['target_name'],
  1922               'page_id' => $page_id,
  1922 							'page_id' => $page_id,
  1923               'namespace' => $namespace,
  1923 							'namespace' => $namespace,
  1924             );
  1924 						);
  1925           break;
  1925 					break;
  1926         case 'delete':
  1926 				case 'delete':
  1927           if ( defined('ENANO_DEMO_MODE') )
  1927 					if ( defined('ENANO_DEMO_MODE') )
  1928           {
  1928 					{
  1929             return Array('mode'=>'error','error'=>$lang->get('acl_err_demo'));
  1929 						return Array('mode'=>'error','error'=>$lang->get('acl_err_demo'));
  1930           }
  1930 					}
  1931           $sql = 'DELETE FROM ' . table_prefix.'acl WHERE target_type='.intval($parms['target_type']).' AND target_id='.intval($parms['target_id']).'
  1931 					$sql = 'DELETE FROM ' . table_prefix.'acl WHERE target_type='.intval($parms['target_type']).' AND target_id='.intval($parms['target_id']).'
  1932             ' . $page_where_clause_lite . ';';
  1932 						' . $page_where_clause_lite . ';';
  1933           $q = $db->sql_query($sql);
  1933 					$q = $db->sql_query($sql);
  1934           if(!$q)
  1934 					if(!$q)
  1935             return Array('mode'=>'error','error'=>$db->get_error());
  1935 						return Array('mode'=>'error','error'=>$db->get_error());
  1936           return Array(
  1936 					return Array(
  1937               'mode' => 'delete',
  1937 							'mode' => 'delete',
  1938               'target_type' => $parms['target_type'],
  1938 							'target_type' => $parms['target_type'],
  1939               'target_id' => $parms['target_id'],
  1939 							'target_id' => $parms['target_id'],
  1940               'target_name' => $parms['target_name'],
  1940 							'target_name' => $parms['target_name'],
  1941               'page_id' => $page_id,
  1941 							'page_id' => $page_id,
  1942               'namespace' => $namespace,
  1942 							'namespace' => $namespace,
  1943             );
  1943 						);
  1944           break;
  1944 					break;
  1945         case 'list_existing':
  1945 				case 'list_existing':
  1946           
  1946 					
  1947           $return = array(
  1947 					$return = array(
  1948               'mode'  => 'list_existing',
  1948 							'mode'  => 'list_existing',
  1949               'key'   => acl_list_draw_key(),
  1949 							'key'   => acl_list_draw_key(),
  1950               'rules' => array()
  1950 							'rules' => array()
  1951             );
  1951 						);
  1952           
  1952 					
  1953           $acl_columns = 'a.' . implode(', a.', $db->columns_in(table_prefix . 'acl'));
  1953 					$acl_columns = 'a.' . implode(', a.', $db->columns_in(table_prefix . 'acl'));
  1954           $users_columns = 'u.' . implode(', u.', $db->columns_in(table_prefix . 'users'));
  1954 					$users_columns = 'u.' . implode(', u.', $db->columns_in(table_prefix . 'users'));
  1955           $groups_columns = 'g.' . implode(', g.', $db->columns_in(table_prefix . 'groups'));
  1955 					$groups_columns = 'g.' . implode(', g.', $db->columns_in(table_prefix . 'groups'));
  1956           $pg_columns = 'p.' . implode(', p.', array('pg_id', 'pg_type', 'pg_name', 'pg_target'));
  1956 					$pg_columns = 'p.' . implode(', p.', array('pg_id', 'pg_type', 'pg_name', 'pg_target'));
  1957           
  1957 					
  1958           $q = $db->sql_query("SELECT a.rule_id, u.username, g.group_name, a.target_type, a.target_id, a.page_id, a.namespace, a.rules, p.pg_name\n"
  1958 					$q = $db->sql_query("SELECT a.rule_id, u.username, g.group_name, a.target_type, a.target_id, a.page_id, a.namespace, a.rules, p.pg_name\n"
  1959                   . "  FROM " . table_prefix . "acl AS a\n"
  1959 									. "  FROM " . table_prefix . "acl AS a\n"
  1960                   . "  LEFT JOIN " . table_prefix . "users AS u\n"
  1960 									. "  LEFT JOIN " . table_prefix . "users AS u\n"
  1961                   . "    ON ( (a.target_type = " . ACL_TYPE_USER . " AND a.target_id = u.user_id) OR (u.user_id IS NULL) )\n"
  1961 									. "    ON ( (a.target_type = " . ACL_TYPE_USER . " AND a.target_id = u.user_id) OR (u.user_id IS NULL) )\n"
  1962                   . "  LEFT JOIN " . table_prefix . "groups AS g\n"
  1962 									. "  LEFT JOIN " . table_prefix . "groups AS g\n"
  1963                   . "    ON ( (a.target_type = " . ACL_TYPE_GROUP . " AND a.target_id = g.group_id) OR (g.group_id IS NULL) )\n"
  1963 									. "    ON ( (a.target_type = " . ACL_TYPE_GROUP . " AND a.target_id = g.group_id) OR (g.group_id IS NULL) )\n"
  1964                   . "  LEFT JOIN " . table_prefix . "page_groups as p\n"
  1964 									. "  LEFT JOIN " . table_prefix . "page_groups as p\n"
  1965                   . "    ON ( (a.namespace = '__PageGroup' AND a.page_id = CAST(p.pg_id AS CHAR)) OR (p.pg_id IS NULL) )\n"
  1965 									. "    ON ( (a.namespace = '__PageGroup' AND a.page_id = CAST(p.pg_id AS CHAR)) OR (p.pg_id IS NULL) )\n"
  1966                   . "  WHERE ( a.target_type = " . ACL_TYPE_USER . " OR a.target_type = " . ACL_TYPE_GROUP . " )\n"
  1966 									. "  WHERE ( a.target_type = " . ACL_TYPE_USER . " OR a.target_type = " . ACL_TYPE_GROUP . " )\n"
  1967                   . "  GROUP BY a.rule_id, $acl_columns, $users_columns, $groups_columns, $pg_columns\n"
  1967 									. "  GROUP BY a.rule_id, $acl_columns, $users_columns, $groups_columns, $pg_columns\n"
  1968                   . "  ORDER BY a.target_type ASC, a.rule_id ASC;"
  1968 									. "  ORDER BY a.target_type ASC, a.rule_id ASC;"
  1969                 );
  1969 								);
  1970           
  1970 					
  1971           if ( !$q )
  1971 					if ( !$q )
  1972             $db->_die();
  1972 						$db->_die();
  1973           
  1973 					
  1974           while ( $row = $db->fetchrow($q) )
  1974 					while ( $row = $db->fetchrow($q) )
  1975           {
  1975 					{
  1976             if ( $row['target_type'] == ACL_TYPE_USER && empty($row['username']) )
  1976 						if ( $row['target_type'] == ACL_TYPE_USER && empty($row['username']) )
  1977             {
  1977 						{
  1978               // This is only done if we have an ACL affecting a user that doesn't exist.
  1978 							// This is only done if we have an ACL affecting a user that doesn't exist.
  1979               // Nice little bit of maintenance to have.
  1979 							// Nice little bit of maintenance to have.
  1980               if ( !$db->sql_query("DELETE FROM " . table_prefix . "acl WHERE rule_id = {$row['rule_id']};") )
  1980 							if ( !$db->sql_query("DELETE FROM " . table_prefix . "acl WHERE rule_id = {$row['rule_id']};") )
  1981                 $db->_die();
  1981 								$db->_die();
  1982               continue;
  1982 							continue;
  1983             }
  1983 						}
  1984             $score = get_acl_rule_score($row['rules']);
  1984 						$score = get_acl_rule_score($row['rules']);
  1985             $deep_limit = ACL_SCALE_MINIMAL_SHADE;
  1985 						$deep_limit = ACL_SCALE_MINIMAL_SHADE;
  1986             // Determine background color of cell by score
  1986 						// Determine background color of cell by score
  1987             if ( $score > 5 )
  1987 						if ( $score > 5 )
  1988             {
  1988 						{
  1989               // high score, show in green
  1989 							// high score, show in green
  1990               $color = 2.5 * $score;
  1990 							$color = 2.5 * $score;
  1991               if ( $color > 255 )
  1991 							if ( $color > 255 )
  1992                 $color = 255;
  1992 								$color = 255;
  1993               $color = round($color);
  1993 							$color = round($color);
  1994               // blend with the colordepth limit
  1994 							// blend with the colordepth limit
  1995               $color = $deep_limit + ( ( 0xFF - $deep_limit ) - ( ( $color / 0xFF ) * ( 0xFF - $deep_limit ) ) );
  1995 							$color = $deep_limit + ( ( 0xFF - $deep_limit ) - ( ( $color / 0xFF ) * ( 0xFF - $deep_limit ) ) );
  1996               $color = dechex($color);
  1996 							$color = dechex($color);
  1997               $color = "{$color}ff{$color}";
  1997 							$color = "{$color}ff{$color}";
  1998             }
  1998 						}
  1999             else if ( $score < -5 )
  1999 						else if ( $score < -5 )
  2000             {
  2000 						{
  2001               // low score, show in red
  2001 							// low score, show in red
  2002               $color = 0 - $score;
  2002 							$color = 0 - $score;
  2003               $color = 2.5 * $color;
  2003 							$color = 2.5 * $color;
  2004               if ( $color > 255 )
  2004 							if ( $color > 255 )
  2005                 $color = 255;
  2005 								$color = 255;
  2006               $color = round($color);
  2006 							$color = round($color);
  2007               // blend with the colordepth limit
  2007 							// blend with the colordepth limit
  2008               $color = $deep_limit + ( ( 0xFF - $deep_limit ) - ( ( $color / 0xFF ) * ( 0xFF - $deep_limit ) ) );
  2008 							$color = $deep_limit + ( ( 0xFF - $deep_limit ) - ( ( $color / 0xFF ) * ( 0xFF - $deep_limit ) ) );
  2009               $color = dechex($color);
  2009 							$color = dechex($color);
  2010               $color = "ff{$color}{$color}";
  2010 							$color = "ff{$color}{$color}";
  2011             }
  2011 						}
  2012             else
  2012 						else
  2013             {
  2013 						{
  2014               $color = 'efefef';
  2014 							$color = 'efefef';
  2015             }
  2015 						}
  2016             
  2016 						
  2017             // Rate rule textually based on its score
  2017 						// Rate rule textually based on its score
  2018             if ( $score >= 70 )
  2018 						if ( $score >= 70 )
  2019               $desc = $lang->get('acl_msg_scale_allow');
  2019 							$desc = $lang->get('acl_msg_scale_allow');
  2020             else if ( $score >= 50 )
  2020 						else if ( $score >= 50 )
  2021               $desc = $lang->get('acl_msg_scale_mostly_allow');
  2021 							$desc = $lang->get('acl_msg_scale_mostly_allow');
  2022             else if ( $score >= 25 )
  2022 						else if ( $score >= 25 )
  2023               $desc = $lang->get('acl_msg_scale_some_allow');
  2023 							$desc = $lang->get('acl_msg_scale_some_allow');
  2024             else if ( $score >= -25 )
  2024 						else if ( $score >= -25 )
  2025               $desc = $lang->get('acl_msg_scale_mixed');
  2025 							$desc = $lang->get('acl_msg_scale_mixed');
  2026             else if ( $score <= -70 )
  2026 						else if ( $score <= -70 )
  2027               $desc = $lang->get('acl_msg_scale_deny');
  2027 							$desc = $lang->get('acl_msg_scale_deny');
  2028             else if ( $score <= -50 )
  2028 						else if ( $score <= -50 )
  2029               $desc = $lang->get('acl_msg_scale_mostly_deny');
  2029 							$desc = $lang->get('acl_msg_scale_mostly_deny');
  2030             else if ( $score <= -25 )
  2030 						else if ( $score <= -25 )
  2031               $desc = $lang->get('acl_msg_scale_some_deny');
  2031 							$desc = $lang->get('acl_msg_scale_some_deny');
  2032             
  2032 						
  2033             // group and user target info
  2033 						// group and user target info
  2034             $info = '';
  2034 						$info = '';
  2035             if ( $row['target_type'] == ACL_TYPE_USER )
  2035 						if ( $row['target_type'] == ACL_TYPE_USER )
  2036               $info = $lang->get('acl_msg_list_user', array( 'username' => $row['username'] )); // "(User: {$row['username']})";
  2036 							$info = $lang->get('acl_msg_list_user', array( 'username' => $row['username'] )); // "(User: {$row['username']})";
  2037             else if ( $row['target_type'] == ACL_TYPE_GROUP )
  2037 						else if ( $row['target_type'] == ACL_TYPE_GROUP )
  2038               $info = $lang->get('acl_msg_list_group', array( 'group' => $row['group_name'] ));
  2038 							$info = $lang->get('acl_msg_list_group', array( 'group' => $row['group_name'] ));
  2039             
  2039 						
  2040             // affected pages info
  2040 						// affected pages info
  2041             if ( $row['page_id'] && $row['namespace'] && $row['namespace'] != '__PageGroup' )
  2041 						if ( $row['page_id'] && $row['namespace'] && $row['namespace'] != '__PageGroup' )
  2042               $info .= $lang->get('acl_msg_list_on_page', array( 'page_name' => "{$row['namespace']}:{$row['page_id']}" ));
  2042 							$info .= $lang->get('acl_msg_list_on_page', array( 'page_name' => "{$row['namespace']}:{$row['page_id']}" ));
  2043             else if ( $row['page_id'] && $row['namespace'] && $row['namespace'] == '__PageGroup' )
  2043 						else if ( $row['page_id'] && $row['namespace'] && $row['namespace'] == '__PageGroup' )
  2044               $info .= $lang->get('acl_msg_list_on_page_group', array( 'page_group' => $row['pg_name'] ));
  2044 							$info .= $lang->get('acl_msg_list_on_page_group', array( 'page_group' => $row['pg_name'] ));
  2045             else
  2045 						else
  2046               $info .= $lang->get('acl_msg_list_entire_site');
  2046 							$info .= $lang->get('acl_msg_list_entire_site');
  2047               
  2047 							
  2048             $score_string = $lang->get('acl_msg_list_score', array
  2048 						$score_string = $lang->get('acl_msg_list_score', array
  2049               (
  2049 							(
  2050                 'score' => $score,
  2050 								'score' => $score,
  2051                 'desc'  => $desc,
  2051 								'desc'  => $desc,
  2052                 'info'  => $info
  2052 								'info'  => $info
  2053                 ));
  2053 								));
  2054             $return['rules'][] = array(
  2054 						$return['rules'][] = array(
  2055               'score_string' => $score_string,
  2055 							'score_string' => $score_string,
  2056               'rule_id'      => $row['rule_id'],
  2056 							'rule_id'      => $row['rule_id'],
  2057               'color'        => $color
  2057 							'color'        => $color
  2058               );
  2058 							);
  2059           }
  2059 					}
  2060           
  2060 					
  2061           break;
  2061 					break;
  2062         case 'list_presets':
  2062 				case 'list_presets':
  2063           $presets = array();
  2063 					$presets = array();
  2064           $q = $db->sql_query('SELECT page_id AS preset_name, rule_id, rules FROM ' . table_prefix . "acl WHERE target_type = " . ACL_TYPE_PRESET . ";");
  2064 					$q = $db->sql_query('SELECT page_id AS preset_name, rule_id, rules FROM ' . table_prefix . "acl WHERE target_type = " . ACL_TYPE_PRESET . ";");
  2065           if ( !$q )
  2065 					if ( !$q )
  2066             $db->die_json();
  2066 						$db->die_json();
  2067           
  2067 					
  2068           while ( $row = $db->fetchrow() )
  2068 					while ( $row = $db->fetchrow() )
  2069           {
  2069 					{
  2070             $row['rules'] = $session->string_to_perm($row['rules']);
  2070 						$row['rules'] = $session->string_to_perm($row['rules']);
  2071             $presets[] = $row;
  2071 						$presets[] = $row;
  2072           }
  2072 					}
  2073           
  2073 					
  2074           return array(
  2074 					return array(
  2075             'mode' => 'list_existing',
  2075 						'mode' => 'list_existing',
  2076             'presets' => $presets
  2076 						'presets' => $presets
  2077           );
  2077 					);
  2078           break;
  2078 					break;
  2079         case 'save_preset':
  2079 				case 'save_preset':
  2080           if ( empty($parms['preset_name']) )
  2080 					if ( empty($parms['preset_name']) )
  2081           {
  2081 					{
  2082             return array(
  2082 						return array(
  2083               'mode' => 'error',
  2083 							'mode' => 'error',
  2084               'error' => $lang->get('acl_err_preset_name_empty')
  2084 							'error' => $lang->get('acl_err_preset_name_empty')
  2085             );
  2085 						);
  2086           }
  2086 					}
  2087           $preset_name = $db->escape($parms['preset_name']);
  2087 					$preset_name = $db->escape($parms['preset_name']);
  2088           $q = $db->sql_query('DELETE FROM ' . table_prefix . "acl WHERE target_type = " . ACL_TYPE_PRESET . " AND page_id = '$preset_name';");
  2088 					$q = $db->sql_query('DELETE FROM ' . table_prefix . "acl WHERE target_type = " . ACL_TYPE_PRESET . " AND page_id = '$preset_name';");
  2089           if ( !$q )
  2089 					if ( !$q )
  2090             $db->die_json();
  2090 						$db->die_json();
  2091           
  2091 					
  2092           $perms = $session->perm_to_string($parms['perms']);
  2092 					$perms = $session->perm_to_string($parms['perms']);
  2093           if ( !$perms )
  2093 					if ( !$perms )
  2094           {
  2094 					{
  2095             return array(
  2095 						return array(
  2096               'mode' => 'error',
  2096 							'mode' => 'error',
  2097               'error' => $lang->get('acl_err_preset_is_blank')
  2097 							'error' => $lang->get('acl_err_preset_is_blank')
  2098             );
  2098 						);
  2099           }
  2099 					}
  2100           
  2100 					
  2101           $perms = $db->escape($perms);
  2101 					$perms = $db->escape($perms);
  2102           $q = $db->sql_query('INSERT INTO ' . table_prefix . "acl(page_id, target_type, rules) VALUES\n"
  2102 					$q = $db->sql_query('INSERT INTO ' . table_prefix . "acl(page_id, target_type, rules) VALUES\n"
  2103                             . "  ( '$preset_name', " . ACL_TYPE_PRESET . ", '$perms' );");
  2103 														. "  ( '$preset_name', " . ACL_TYPE_PRESET . ", '$perms' );");
  2104           if ( !$q )
  2104 					if ( !$q )
  2105             $db->die_json();
  2105 						$db->die_json();
  2106           
  2106 					
  2107           return array(
  2107 					return array(
  2108               'mode' => 'success'
  2108 							'mode' => 'success'
  2109             );
  2109 						);
  2110           break;
  2110 					break;
  2111         case 'trace':
  2111 				case 'trace':
  2112           list($targetpid, $targetns) = RenderMan::strToPageID($parms['page']);
  2112 					list($targetpid, $targetns) = RenderMan::strToPageID($parms['page']);
  2113           try
  2113 					try
  2114           {
  2114 					{
  2115             $perms = $session->fetch_page_acl_user($parms['user'], $targetpid, $targetns);
  2115 						$perms = $session->fetch_page_acl_user($parms['user'], $targetpid, $targetns);
  2116             $perm_table = array(
  2116 						$perm_table = array(
  2117                 AUTH_ALLOW => 'acl_lbl_field_allow',
  2117 								AUTH_ALLOW => 'acl_lbl_field_allow',
  2118                 AUTH_WIKIMODE => 'acl_lbl_field_wikimode',
  2118 								AUTH_WIKIMODE => 'acl_lbl_field_wikimode',
  2119                 AUTH_DISALLOW => 'acl_lbl_field_disallow',
  2119 								AUTH_DISALLOW => 'acl_lbl_field_disallow',
  2120                 AUTH_DENY => 'acl_lbl_field_deny'
  2120 								AUTH_DENY => 'acl_lbl_field_deny'
  2121               );
  2121 							);
  2122             
  2122 						
  2123             $return = array(
  2123 						$return = array(
  2124               'mode' => 'trace',
  2124 							'mode' => 'trace',
  2125               'perms' => array()
  2125 							'perms' => array()
  2126             );
  2126 						);
  2127             
  2127 						
  2128             foreach ( $perms->perm_resolve_table as $perm_type => $lookup_data )
  2128 						foreach ( $perms->perm_resolve_table as $perm_type => $lookup_data )
  2129             {
  2129 						{
  2130               if ( !$session->check_acl_scope($perm_type, $targetns) )
  2130 							if ( !$session->check_acl_scope($perm_type, $targetns) )
  2131                 continue;
  2131 								continue;
  2132               
  2132 							
  2133               $src_l10n = $lang->get($session->acl_inherit_lang_table[$lookup_data['src']], $lookup_data);
  2133 							$src_l10n = $lang->get($session->acl_inherit_lang_table[$lookup_data['src']], $lookup_data);
  2134               $divclass = preg_replace('/^acl_inherit_/', '', $session->acl_inherit_lang_table[$lookup_data['src']]);
  2134 							$divclass = preg_replace('/^acl_inherit_/', '', $session->acl_inherit_lang_table[$lookup_data['src']]);
  2135               $perm_string = $lang->get($perm_table[$perms->perms[$perm_type]]);
  2135 							$perm_string = $lang->get($perm_table[$perms->perms[$perm_type]]);
  2136               $perm_name = $lang->get($session->acl_descs[$perm_type]);
  2136 							$perm_name = $lang->get($session->acl_descs[$perm_type]);
  2137               
  2137 							
  2138               $return['perms'][$perm_type] = array(
  2138 							$return['perms'][$perm_type] = array(
  2139                   'divclass' => "acl_inherit acl_$divclass",
  2139 									'divclass' => "acl_inherit acl_$divclass",
  2140                   'perm_type' => $perm_type,
  2140 									'perm_type' => $perm_type,
  2141                   'perm_name' => $perm_name,
  2141 									'perm_name' => $perm_name,
  2142                   'perm_value' => $perm_string,
  2142 									'perm_value' => $perm_string,
  2143                   'perm_src' => $src_l10n,
  2143 									'perm_src' => $src_l10n,
  2144                   'rule_id' => intval($lookup_data['rule_id']),
  2144 									'rule_id' => intval($lookup_data['rule_id']),
  2145                   'bad_deps' => $perms->acl_check_deps($perm_type, true)
  2145 									'bad_deps' => $perms->acl_check_deps($perm_type, true)
  2146                 );
  2146 								);
  2147             }
  2147 						}
  2148             
  2148 						
  2149             // group rules if possible
  2149 						// group rules if possible
  2150             $return['groups'] = array();
  2150 						$return['groups'] = array();
  2151             foreach ( $return['perms'] as $rule )
  2151 						foreach ( $return['perms'] as $rule )
  2152             {
  2152 						{
  2153               if ( !isset($return['groups'][$rule['rule_id']]) )
  2153 							if ( !isset($return['groups'][$rule['rule_id']]) )
  2154               {
  2154 							{
  2155                 $return['groups'][$rule['rule_id']] = array();
  2155 								$return['groups'][$rule['rule_id']] = array();
  2156               }
  2156 							}
  2157               $return['groups'][$rule['rule_id']][] = $rule['perm_type'];
  2157 							$return['groups'][$rule['rule_id']][] = $rule['perm_type'];
  2158             }
  2158 						}
  2159           }
  2159 					}
  2160           catch ( Exception $e )
  2160 					catch ( Exception $e )
  2161           {
  2161 					{
  2162             $return = array(
  2162 						$return = array(
  2163                 'mode' => 'error',
  2163 								'mode' => 'error',
  2164                 'error' => $e->getMessage()
  2164 								'error' => $e->getMessage()
  2165               );
  2165 							);
  2166           }
  2166 					}
  2167           
  2167 					
  2168           break;
  2168 					break;
  2169         default:
  2169 				default:
  2170           return Array('mode'=>'error','error'=>'Hacking attempt');
  2170 					return Array('mode'=>'error','error'=>'Hacking attempt');
  2171           break;
  2171 					break;
  2172       }
  2172 			}
  2173     }
  2173 		}
  2174     return $return;
  2174 		return $return;
  2175   }
  2175 	}
  2176   
  2176 	
  2177   /**
  2177 	/**
  2178    * Same as PageUtils::acl_editor(), but the parms are a JSON string instead of an array. This also returns a JSON string.
  2178  	* Same as PageUtils::acl_editor(), but the parms are a JSON string instead of an array. This also returns a JSON string.
  2179    * @param string $parms Same as PageUtils::acl_editor/$parms, but should be a valid JSON string.
  2179  	* @param string $parms Same as PageUtils::acl_editor/$parms, but should be a valid JSON string.
  2180    * @return string
  2180  	* @return string
  2181    */
  2181  	*/
  2182    
  2182  	
  2183   public static function acl_json($parms = '{ }')
  2183 	public static function acl_json($parms = '{ }')
  2184   {
  2184 	{
  2185     global $db, $session, $paths, $template, $plugins; // Common objects
  2185 		global $db, $session, $paths, $template, $plugins; // Common objects
  2186     try
  2186 		try
  2187     {
  2187 		{
  2188       $parms = enano_json_decode($parms);
  2188 			$parms = enano_json_decode($parms);
  2189     }
  2189 		}
  2190     catch ( Zend_Json_Exception $e )
  2190 		catch ( Zend_Json_Exception $e )
  2191     {
  2191 		{
  2192       $parms = array();
  2192 			$parms = array();
  2193     }
  2193 		}
  2194     $ret = PageUtils::acl_editor($parms);
  2194 		$ret = PageUtils::acl_editor($parms);
  2195     $ret = enano_json_encode($ret);
  2195 		$ret = enano_json_encode($ret);
  2196     return $ret;
  2196 		return $ret;
  2197   }
  2197 	}
  2198   
  2198 	
  2199   /**
  2199 	/**
  2200    * A non-Javascript frontend for the ACL API.
  2200  	* A non-Javascript frontend for the ACL API.
  2201    * @param array The request data, if any, this should be in the format required by PageUtils::acl_editor()
  2201  	* @param array The request data, if any, this should be in the format required by PageUtils::acl_editor()
  2202    */
  2202  	*/
  2203    
  2203  	
  2204   public static function aclmanager($parms)
  2204 	public static function aclmanager($parms)
  2205   {
  2205 	{
  2206     global $db, $session, $paths, $template, $plugins; // Common objects
  2206 		global $db, $session, $paths, $template, $plugins; // Common objects
  2207     global $lang;
  2207 		global $lang;
  2208     ob_start();
  2208 		ob_start();
  2209     // Convenience
  2209 		// Convenience
  2210     $formstart = '<form 
  2210 		$formstart = '<form 
  2211                     action="' . makeUrl($paths->page, 'do=aclmanager', true) . '"
  2211 										action="' . makeUrl($paths->page, 'do=aclmanager', true) . '"
  2212                     method="post" enctype="multipart/form-data"
  2212 										method="post" enctype="multipart/form-data"
  2213                     onsubmit="if(!submitAuthorized) return false;"
  2213 										onsubmit="if(!submitAuthorized) return false;"
  2214                     >';
  2214 										>';
  2215     $formend   = '</form>';
  2215 		$formend   = '</form>';
  2216     $parms    = PageUtils::acl_preprocess($parms);
  2216 		$parms    = PageUtils::acl_preprocess($parms);
  2217     $response = PageUtils::acl_editor($parms);
  2217 		$response = PageUtils::acl_editor($parms);
  2218     $response = PageUtils::acl_postprocess($response);
  2218 		$response = PageUtils::acl_postprocess($response);
  2219     
  2219 		
  2220     //die('<pre>' . htmlspecialchars(print_r($response, true)) . '</pre>');
  2220 		//die('<pre>' . htmlspecialchars(print_r($response, true)) . '</pre>');
  2221     
  2221 		
  2222     switch($response['mode'])
  2222 		switch($response['mode'])
  2223     {
  2223 		{
  2224       case 'debug':
  2224 			case 'debug':
  2225         echo '<pre>' . htmlspecialchars($response['text']) . '</pre>';
  2225 				echo '<pre>' . htmlspecialchars($response['text']) . '</pre>';
  2226         break;
  2226 				break;
  2227       case 'stage1':
  2227 			case 'stage1':
  2228         echo '<h3>' . $lang->get('acl_lbl_welcome_title') . '</h3>
  2228 				echo '<h3>' . $lang->get('acl_lbl_welcome_title') . '</h3>
  2229               <p>' . $lang->get('acl_lbl_welcome_body') . '</p>';
  2229 							<p>' . $lang->get('acl_lbl_welcome_body') . '</p>';
  2230         echo $formstart;
  2230 				echo $formstart;
  2231         echo '<p><label><input type="radio" name="data[target_type]" value="' . ACL_TYPE_GROUP . '" checked="checked" /> ' . $lang->get('acl_radio_usergroup') . '</label></p>
  2231 				echo '<p><label><input type="radio" name="data[target_type]" value="' . ACL_TYPE_GROUP . '" checked="checked" /> ' . $lang->get('acl_radio_usergroup') . '</label></p>
  2232               <p><select name="data[target_id_grp]">';
  2232 							<p><select name="data[target_id_grp]">';
  2233         foreach ( $response['groups'] as $group )
  2233 				foreach ( $response['groups'] as $group )
  2234         {
  2234 				{
  2235           echo '<option value="' . $group['id'] . '">' . $group['name'] . '</option>';
  2235 					echo '<option value="' . $group['id'] . '">' . $group['name'] . '</option>';
  2236         }
  2236 				}
  2237         
  2237 				
  2238         // page group selector
  2238 				// page group selector
  2239         $groupsel = '';
  2239 				$groupsel = '';
  2240         if ( count($response['page_groups']) > 0 )
  2240 				if ( count($response['page_groups']) > 0 )
  2241         {
  2241 				{
  2242           $groupsel = '<p><label><input type="radio" name="data[scope]" value="page_group" /> ' . $lang->get('acl_radio_scope_pagegroup') . '</label></p>
  2242 					$groupsel = '<p><label><input type="radio" name="data[scope]" value="page_group" /> ' . $lang->get('acl_radio_scope_pagegroup') . '</label></p>
  2243                        <p><select name="data[pg_id]">';
  2243  											<p><select name="data[pg_id]">';
  2244           foreach ( $response['page_groups'] as $grp )
  2244 					foreach ( $response['page_groups'] as $grp )
  2245           {
  2245 					{
  2246             $groupsel .= '<option value="' . $grp['id'] . '">' . htmlspecialchars($grp['name']) . '</option>';
  2246 						$groupsel .= '<option value="' . $grp['id'] . '">' . htmlspecialchars($grp['name']) . '</option>';
  2247           }
  2247 					}
  2248           $groupsel .= '</select></p>';
  2248 					$groupsel .= '</select></p>';
  2249         }
  2249 				}
  2250         
  2250 				
  2251         echo '</select></p>
  2251 				echo '</select></p>
  2252               <p><label><input type="radio" name="data[target_type]" value="' . ACL_TYPE_USER . '" /> ' . $lang->get('acl_radio_user') . '</label></p>
  2252 							<p><label><input type="radio" name="data[target_type]" value="' . ACL_TYPE_USER . '" /> ' . $lang->get('acl_radio_user') . '</label></p>
  2253               <p>' . $template->username_field('data[target_id_user]') . '</p>
  2253 							<p>' . $template->username_field('data[target_id_user]') . '</p>
  2254               <p>' . $lang->get('acl_lbl_scope') . '</p>
  2254 							<p>' . $lang->get('acl_lbl_scope') . '</p>
  2255               <p><label><input name="data[scope]" value="only_this" type="radio" checked="checked" /> ' . $lang->get('acl_radio_scope_thispage') . '</p>
  2255 							<p><label><input name="data[scope]" value="only_this" type="radio" checked="checked" /> ' . $lang->get('acl_radio_scope_thispage') . '</p>
  2256               ' . $groupsel . '
  2256 							' . $groupsel . '
  2257               <p><label><input name="data[scope]" value="entire_site" type="radio" /> ' . $lang->get('acl_radio_scope_wholesite') . '</p>
  2257 							<p><label><input name="data[scope]" value="entire_site" type="radio" /> ' . $lang->get('acl_radio_scope_wholesite') . '</p>
  2258               <div style="margin: 0 auto 0 0; text-align: right;">
  2258 							<div style="margin: 0 auto 0 0; text-align: right;">
  2259                 <input name="data[mode]" value="seltarget" type="hidden" />
  2259 								<input name="data[mode]" value="seltarget" type="hidden" />
  2260                 <input type="hidden" name="data[page_id]" value="' . $paths->page_id . '" />
  2260 								<input type="hidden" name="data[page_id]" value="' . $paths->page_id . '" />
  2261                 <input type="hidden" name="data[namespace]" value="' . $paths->namespace . '" />
  2261 								<input type="hidden" name="data[namespace]" value="' . $paths->namespace . '" />
  2262                 <input type="submit" value="' . htmlspecialchars($lang->get('etc_wizard_next')) . '" />
  2262 								<input type="submit" value="' . htmlspecialchars($lang->get('etc_wizard_next')) . '" />
  2263               </div>';
  2263 							</div>';
  2264         echo $formend;
  2264 				echo $formend;
  2265         break;
  2265 				break;
  2266       case 'success':
  2266 			case 'success':
  2267         echo '<div class="info-box">
  2267 				echo '<div class="info-box">
  2268                 <b>' . $lang->get('acl_lbl_save_success_title') . '</b><br />
  2268 								<b>' . $lang->get('acl_lbl_save_success_title') . '</b><br />
  2269                 ' . $lang->get('acl_lbl_save_success_body', array( 'target_name' => $response['target_name'] )) . '<br />
  2269 								' . $lang->get('acl_lbl_save_success_body', array( 'target_name' => $response['target_name'] )) . '<br />
  2270                 ' . $formstart . '
  2270 								' . $formstart . '
  2271                 <input type="hidden" name="data[mode]" value="seltarget" />
  2271 								<input type="hidden" name="data[mode]" value="seltarget" />
  2272                 <input type="hidden" name="data[target_type]" value="' . $response['target_type'] . '" />
  2272 								<input type="hidden" name="data[target_type]" value="' . $response['target_type'] . '" />
  2273                 <input type="hidden" name="data[target_id_user]" value="' . ( ( intval($response['target_type']) == ACL_TYPE_USER ) ? $response['target_name'] : $response['target_id'] ) .'" />
  2273 								<input type="hidden" name="data[target_id_user]" value="' . ( ( intval($response['target_type']) == ACL_TYPE_USER ) ? $response['target_name'] : $response['target_id'] ) .'" />
  2274                 <input type="hidden" name="data[target_id_grp]"  value="' . ( ( intval($response['target_type']) == ACL_TYPE_USER ) ? $response['target_name'] : $response['target_id'] ) .'" />
  2274 								<input type="hidden" name="data[target_id_grp]"  value="' . ( ( intval($response['target_type']) == ACL_TYPE_USER ) ? $response['target_name'] : $response['target_id'] ) .'" />
  2275                 <input type="hidden" name="data[scope]" value="' . ( ( $response['page_id'] ) ? 'only_this' : 'entire_site' ) . '" />
  2275 								<input type="hidden" name="data[scope]" value="' . ( ( $response['page_id'] ) ? 'only_this' : 'entire_site' ) . '" />
  2276                 <input type="hidden" name="data[page_id]" value="' . ( ( $response['page_id'] ) ? $response['page_id'] : 'false' ) . '" />
  2276 								<input type="hidden" name="data[page_id]" value="' . ( ( $response['page_id'] ) ? $response['page_id'] : 'false' ) . '" />
  2277                 <input type="hidden" name="data[namespace]" value="' . ( ( $response['namespace'] ) ? $response['namespace'] : 'false' ) . '" />
  2277 								<input type="hidden" name="data[namespace]" value="' . ( ( $response['namespace'] ) ? $response['namespace'] : 'false' ) . '" />
  2278                 <input type="submit" value="' . $lang->get('acl_btn_returnto_editor') . '" /> <input type="submit" name="data[act_go_stage1]" value="' . $lang->get('acl_btn_returnto_userscope') . '" />
  2278 								<input type="submit" value="' . $lang->get('acl_btn_returnto_editor') . '" /> <input type="submit" name="data[act_go_stage1]" value="' . $lang->get('acl_btn_returnto_userscope') . '" />
  2279                 ' . $formend . '
  2279 								' . $formend . '
  2280               </div>';
  2280 							</div>';
  2281         break;
  2281 				break;
  2282       case 'delete':
  2282 			case 'delete':
  2283         echo '<div class="info-box">
  2283 				echo '<div class="info-box">
  2284                 <b>' . $lang->get('acl_lbl_delete_success_title') . '</b><br />
  2284 								<b>' . $lang->get('acl_lbl_delete_success_title') . '</b><br />
  2285                 ' . $lang->get('acl_lbl_delete_success_body', array('target_name' => $response['target_name'])) . '<br />
  2285 								' . $lang->get('acl_lbl_delete_success_body', array('target_name' => $response['target_name'])) . '<br />
  2286                 ' . $formstart . '
  2286 								' . $formstart . '
  2287                 <input type="hidden" name="data[mode]" value="seltarget" />
  2287 								<input type="hidden" name="data[mode]" value="seltarget" />
  2288                 <input type="hidden" name="data[target_type]" value="' . $response['target_type'] . '" />
  2288 								<input type="hidden" name="data[target_type]" value="' . $response['target_type'] . '" />
  2289                 <input type="hidden" name="data[target_id_user]" value="' . ( ( intval($response['target_type']) == ACL_TYPE_USER ) ? $response['target_name'] : $response['target_id'] ) .'" />
  2289 								<input type="hidden" name="data[target_id_user]" value="' . ( ( intval($response['target_type']) == ACL_TYPE_USER ) ? $response['target_name'] : $response['target_id'] ) .'" />
  2290                 <input type="hidden" name="data[target_id_grp]"  value="' . ( ( intval($response['target_type']) == ACL_TYPE_USER ) ? $response['target_name'] : $response['target_id'] ) .'" />
  2290 								<input type="hidden" name="data[target_id_grp]"  value="' . ( ( intval($response['target_type']) == ACL_TYPE_USER ) ? $response['target_name'] : $response['target_id'] ) .'" />
  2291                 <input type="hidden" name="data[scope]" value="' . ( ( $response['page_id'] ) ? 'only_this' : 'entire_site' ) . '" />
  2291 								<input type="hidden" name="data[scope]" value="' . ( ( $response['page_id'] ) ? 'only_this' : 'entire_site' ) . '" />
  2292                 <input type="hidden" name="data[page_id]" value="' . ( ( $response['page_id'] ) ? $response['page_id'] : 'false' ) . '" />
  2292 								<input type="hidden" name="data[page_id]" value="' . ( ( $response['page_id'] ) ? $response['page_id'] : 'false' ) . '" />
  2293                 <input type="hidden" name="data[namespace]" value="' . ( ( $response['namespace'] ) ? $response['namespace'] : 'false' ) . '" />
  2293 								<input type="hidden" name="data[namespace]" value="' . ( ( $response['namespace'] ) ? $response['namespace'] : 'false' ) . '" />
  2294                 <input type="submit" value="' . $lang->get('acl_btn_returnto_editor') . '" /> <input type="submit" name="data[act_go_stage1]" value="' . $lang->get('acl_btn_returnto_userscope') . '" />
  2294 								<input type="submit" value="' . $lang->get('acl_btn_returnto_editor') . '" /> <input type="submit" name="data[act_go_stage1]" value="' . $lang->get('acl_btn_returnto_userscope') . '" />
  2295                 ' . $formend . '
  2295 								' . $formend . '
  2296               </div>';
  2296 							</div>';
  2297         break;
  2297 				break;
  2298       case 'seltarget':
  2298 			case 'seltarget':
  2299         if ( $response['type'] == 'edit' )
  2299 				if ( $response['type'] == 'edit' )
  2300         {
  2300 				{
  2301           echo '<h3>' . $lang->get('acl_lbl_editwin_title_edit') . '</h3>';
  2301 					echo '<h3>' . $lang->get('acl_lbl_editwin_title_edit') . '</h3>';
  2302         }
  2302 				}
  2303         else
  2303 				else
  2304         {
  2304 				{
  2305           echo '<h3>' . $lang->get('acl_lbl_editwin_title_create') . '</h3>';
  2305 					echo '<h3>' . $lang->get('acl_lbl_editwin_title_create') . '</h3>';
  2306         }
  2306 				}
  2307         $type  = ( $response['target_type'] == ACL_TYPE_GROUP ) ? $lang->get('acl_target_type_group') : $lang->get('acl_target_type_user');
  2307 				$type  = ( $response['target_type'] == ACL_TYPE_GROUP ) ? $lang->get('acl_target_type_group') : $lang->get('acl_target_type_user');
  2308         $scope = ( $response['page_id'] ) ? ( $response['namespace'] == '__PageGroup' ? $lang->get('acl_scope_type_pagegroup') : $lang->get('acl_scope_type_thispage') ) : $lang->get('acl_scope_type_wholesite');
  2308 				$scope = ( $response['page_id'] ) ? ( $response['namespace'] == '__PageGroup' ? $lang->get('acl_scope_type_pagegroup') : $lang->get('acl_scope_type_thispage') ) : $lang->get('acl_scope_type_wholesite');
  2309         $subs = array(
  2309 				$subs = array(
  2310             'target_type' => $type,
  2310 						'target_type' => $type,
  2311             'target' => $response['target_name'],
  2311 						'target' => $response['target_name'],
  2312             'scope_type' => $scope
  2312 						'scope_type' => $scope
  2313           );
  2313 					);
  2314         echo $lang->get('acl_lbl_editwin_body', $subs);
  2314 				echo $lang->get('acl_lbl_editwin_body', $subs);
  2315         echo $formstart;
  2315 				echo $formstart;
  2316         $parser = $template->makeParserText( $response['template']['acl_field_begin'] );
  2316 				$parser = $template->makeParserText( $response['template']['acl_field_begin'] );
  2317         echo $parser->run();
  2317 				echo $parser->run();
  2318         $parser = $template->makeParserText( $response['template']['acl_field_item'] );
  2318 				$parser = $template->makeParserText( $response['template']['acl_field_item'] );
  2319         $cls = 'row2';
  2319 				$cls = 'row2';
  2320         foreach ( $response['acl_types'] as $acl_type => $value )
  2320 				foreach ( $response['acl_types'] as $acl_type => $value )
  2321         {
  2321 				{
  2322           $vars = Array(
  2322 					$vars = Array(
  2323               'FIELD_INHERIT_CHECKED' => '',
  2323 							'FIELD_INHERIT_CHECKED' => '',
  2324               'FIELD_DENY_CHECKED' => '',
  2324 							'FIELD_DENY_CHECKED' => '',
  2325               'FIELD_DISALLOW_CHECKED' => '',
  2325 							'FIELD_DISALLOW_CHECKED' => '',
  2326               'FIELD_WIKIMODE_CHECKED' => '',
  2326 							'FIELD_WIKIMODE_CHECKED' => '',
  2327               'FIELD_ALLOW_CHECKED' => '',
  2327 							'FIELD_ALLOW_CHECKED' => '',
  2328             );
  2328 						);
  2329           $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2329 					$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2330           $vars['ROW_CLASS'] = $cls;
  2330 					$vars['ROW_CLASS'] = $cls;
  2331           
  2331 					
  2332           switch ( $response['current_perms'][$acl_type] )
  2332 					switch ( $response['current_perms'][$acl_type] )
  2333           {
  2333 					{
  2334             case 'i':
  2334 						case 'i':
  2335             default:
  2335 						default:
  2336               $vars['FIELD_INHERIT_CHECKED'] = 'checked="checked"';
  2336 							$vars['FIELD_INHERIT_CHECKED'] = 'checked="checked"';
  2337               break;
  2337 							break;
  2338             case AUTH_ALLOW:
  2338 						case AUTH_ALLOW:
  2339               $vars['FIELD_ALLOW_CHECKED'] = 'checked="checked"';
  2339 							$vars['FIELD_ALLOW_CHECKED'] = 'checked="checked"';
  2340               break;
  2340 							break;
  2341             case AUTH_WIKIMODE:
  2341 						case AUTH_WIKIMODE:
  2342               $vars['FIELD_WIKIMODE_CHECKED'] = 'checked="checked"';
  2342 							$vars['FIELD_WIKIMODE_CHECKED'] = 'checked="checked"';
  2343               break;
  2343 							break;
  2344             case AUTH_DISALLOW:
  2344 						case AUTH_DISALLOW:
  2345               $vars['FIELD_DISALLOW_CHECKED'] = 'checked="checked"';
  2345 							$vars['FIELD_DISALLOW_CHECKED'] = 'checked="checked"';
  2346               break;
  2346 							break;
  2347              case AUTH_DENY:
  2347  						case AUTH_DENY:
  2348               $vars['FIELD_DENY_CHECKED'] = 'checked="checked"';
  2348 							$vars['FIELD_DENY_CHECKED'] = 'checked="checked"';
  2349               break;
  2349 							break;
  2350           }
  2350 					}
  2351           $vars['FIELD_NAME'] = 'data[perms][' . $acl_type . ']';
  2351 					$vars['FIELD_NAME'] = 'data[perms][' . $acl_type . ']';
  2352           if ( preg_match('/^([a-z0-9_]+)$/', $response['acl_descs'][$acl_type]) )
  2352 					if ( preg_match('/^([a-z0-9_]+)$/', $response['acl_descs'][$acl_type]) )
  2353           {
  2353 					{
  2354             $vars['FIELD_DESC'] = $lang->get($response['acl_descs'][$acl_type]);
  2354 						$vars['FIELD_DESC'] = $lang->get($response['acl_descs'][$acl_type]);
  2355           }
  2355 					}
  2356           else
  2356 					else
  2357           {
  2357 					{
  2358             $vars['FIELD_DESC'] = $response['acl_descs'][$acl_type];
  2358 						$vars['FIELD_DESC'] = $response['acl_descs'][$acl_type];
  2359           }
  2359 					}
  2360           $parser->assign_vars($vars);
  2360 					$parser->assign_vars($vars);
  2361           echo $parser->run();
  2361 					echo $parser->run();
  2362         }
  2362 				}
  2363         $parser = $template->makeParserText( $response['template']['acl_field_end'] );
  2363 				$parser = $template->makeParserText( $response['template']['acl_field_end'] );
  2364         echo $parser->run();
  2364 				echo $parser->run();
  2365         echo '<div style="margin: 10px auto 0 0; text-align: right;">
  2365 				echo '<div style="margin: 10px auto 0 0; text-align: right;">
  2366                 <input name="data[mode]" value="save_' . $response['type'] . '" type="hidden" />
  2366 								<input name="data[mode]" value="save_' . $response['type'] . '" type="hidden" />
  2367                 <input type="hidden" name="data[page_id]" value="'   . (( $response['page_id']   ) ? $response['page_id']   : 'false') . '" />
  2367 								<input type="hidden" name="data[page_id]" value="'   . (( $response['page_id']   ) ? $response['page_id']   : 'false') . '" />
  2368                 <input type="hidden" name="data[namespace]" value="' . (( $response['namespace'] ) ? $response['namespace'] : 'false') . '" />
  2368 								<input type="hidden" name="data[namespace]" value="' . (( $response['namespace'] ) ? $response['namespace'] : 'false') . '" />
  2369                 <input type="hidden" name="data[target_type]" value="' . $response['target_type'] . '" />
  2369 								<input type="hidden" name="data[target_type]" value="' . $response['target_type'] . '" />
  2370                 <input type="hidden" name="data[target_id]" value="' . $response['target_id'] . '" />
  2370 								<input type="hidden" name="data[target_id]" value="' . $response['target_id'] . '" />
  2371                 <input type="hidden" name="data[target_name]" value="' . $response['target_name'] . '" />
  2371 								<input type="hidden" name="data[target_name]" value="' . $response['target_name'] . '" />
  2372                 ' . ( ( $response['type'] == 'edit' ) ? '<input type="submit" value="' . $lang->get('etc_save_changes') . '" />&nbsp;&nbsp;<input type="submit" name="data[act_delete_rule]" value="' . $lang->get('acl_btn_deleterule') . '" style="color: #AA0000;" onclick="return confirm(\'' . addslashes($lang->get('acl_msg_deleterule_confirm')) . '\');" />' : '<input type="submit" value="' . $lang->get('acl_btn_createrule') . '" />' ) . '
  2372 								' . ( ( $response['type'] == 'edit' ) ? '<input type="submit" value="' . $lang->get('etc_save_changes') . '" />&nbsp;&nbsp;<input type="submit" name="data[act_delete_rule]" value="' . $lang->get('acl_btn_deleterule') . '" style="color: #AA0000;" onclick="return confirm(\'' . addslashes($lang->get('acl_msg_deleterule_confirm')) . '\');" />' : '<input type="submit" value="' . $lang->get('acl_btn_createrule') . '" />' ) . '
  2373               </div>';
  2373 							</div>';
  2374         echo $formend;
  2374 				echo $formend;
  2375         break;
  2375 				break;
  2376       case 'error':
  2376 			case 'error':
  2377         ob_end_clean();
  2377 				ob_end_clean();
  2378         die_friendly('Error occurred', '<p>Error returned by permissions API:</p><pre>' . htmlspecialchars($response['error']) . '</pre>');
  2378 				die_friendly('Error occurred', '<p>Error returned by permissions API:</p><pre>' . htmlspecialchars($response['error']) . '</pre>');
  2379         break;
  2379 				break;
  2380     }
  2380 		}
  2381     $ret = ob_get_contents();
  2381 		$ret = ob_get_contents();
  2382     ob_end_clean();
  2382 		ob_end_clean();
  2383     echo
  2383 		echo
  2384       $template->getHeader() .
  2384 			$template->getHeader() .
  2385       $ret .
  2385 			$ret .
  2386       $template->getFooter();
  2386 			$template->getFooter();
  2387   }
  2387 	}
  2388   
  2388 	
  2389   /**
  2389 	/**
  2390    * Preprocessor to turn the form-submitted data from the ACL editor into something the backend can handle
  2390  	* Preprocessor to turn the form-submitted data from the ACL editor into something the backend can handle
  2391    * @param array The posted data
  2391  	* @param array The posted data
  2392    * @return array
  2392  	* @return array
  2393    * @access private
  2393  	* @access private
  2394    */
  2394  	*/
  2395    
  2395  	
  2396   public static function acl_preprocess($parms)
  2396 	public static function acl_preprocess($parms)
  2397   {
  2397 	{
  2398     if ( !isset($parms['mode']) )
  2398 		if ( !isset($parms['mode']) )
  2399       // Nothing to do
  2399 			// Nothing to do
  2400       return $parms;
  2400 			return $parms;
  2401     switch ( $parms['mode'] )
  2401 		switch ( $parms['mode'] )
  2402     {
  2402 		{
  2403       case 'seltarget':
  2403 			case 'seltarget':
  2404         
  2404 				
  2405         // Who's affected?
  2405 				// Who's affected?
  2406         $parms['target_type'] = intval( $parms['target_type'] );
  2406 				$parms['target_type'] = intval( $parms['target_type'] );
  2407         $parms['target_id'] = ( $parms['target_type'] == ACL_TYPE_GROUP ) ? $parms['target_id_grp'] : $parms['target_id_user'];
  2407 				$parms['target_id'] = ( $parms['target_type'] == ACL_TYPE_GROUP ) ? $parms['target_id_grp'] : $parms['target_id_user'];
  2408         
  2408 				
  2409       case 'save_edit':
  2409 			case 'save_edit':
  2410       case 'save_new':
  2410 			case 'save_new':
  2411         if ( isset($parms['act_delete_rule']) )
  2411 				if ( isset($parms['act_delete_rule']) )
  2412         {
  2412 				{
  2413           $parms['mode'] = 'delete';
  2413 					$parms['mode'] = 'delete';
  2414         }
  2414 				}
  2415         
  2415 				
  2416         // Scope (just this page or entire site?)
  2416 				// Scope (just this page or entire site?)
  2417         if ( $parms['scope'] == 'entire_site' || ( $parms['page_id'] == 'false' && $parms['namespace'] == 'false' ) )
  2417 				if ( $parms['scope'] == 'entire_site' || ( $parms['page_id'] == 'false' && $parms['namespace'] == 'false' ) )
  2418         {
  2418 				{
  2419           $parms['page_id']   = false;
  2419 					$parms['page_id']   = false;
  2420           $parms['namespace'] = false;
  2420 					$parms['namespace'] = false;
  2421         }
  2421 				}
  2422         else if ( $parms['scope'] == 'page_group' )
  2422 				else if ( $parms['scope'] == 'page_group' )
  2423         {
  2423 				{
  2424           $parms['page_id'] = $parms['pg_id'];
  2424 					$parms['page_id'] = $parms['pg_id'];
  2425           $parms['namespace'] = '__PageGroup';
  2425 					$parms['namespace'] = '__PageGroup';
  2426         }
  2426 				}
  2427         
  2427 				
  2428         break;
  2428 				break;
  2429     }
  2429 		}
  2430     
  2430 		
  2431     if ( isset($parms['act_go_stage1']) )
  2431 		if ( isset($parms['act_go_stage1']) )
  2432     {
  2432 		{
  2433       $parms = array(
  2433 			$parms = array(
  2434           'mode' => 'listgroups'
  2434 					'mode' => 'listgroups'
  2435         );
  2435 				);
  2436     }
  2436 		}
  2437     
  2437 		
  2438     return $parms;
  2438 		return $parms;
  2439   }
  2439 	}
  2440   
  2440 	
  2441   public static function acl_postprocess($response)
  2441 	public static function acl_postprocess($response)
  2442   {
  2442 	{
  2443     if(!isset($response['mode']))
  2443 		if(!isset($response['mode']))
  2444     {
  2444 		{
  2445       if ( isset($response['groups']) )
  2445 			if ( isset($response['groups']) )
  2446         $response['mode'] = 'stage1';
  2446 				$response['mode'] = 'stage1';
  2447       else
  2447 			else
  2448         $response = Array(
  2448 				$response = Array(
  2449             'mode' => 'error',
  2449 						'mode' => 'error',
  2450             'error' => 'Invalid action passed by API backend.',
  2450 						'error' => 'Invalid action passed by API backend.',
  2451           );
  2451 					);
  2452     }
  2452 		}
  2453     return $response;
  2453 		return $response;
  2454   }
  2454 	}
  2455    
  2455  	
  2456 }
  2456 }
  2457 
  2457 
  2458 /**
  2458 /**
  2459  * Generates a graphical key showing how the ACL rule list works.
  2459  * Generates a graphical key showing how the ACL rule list works.
  2460  * @return string
  2460  * @return string
  2461  */
  2461  */
  2462 
  2462 
  2463 function acl_list_draw_key()
  2463 function acl_list_draw_key()
  2464 {
  2464 {
  2465   $out  = '<div style="width: 460px; margin: 0 auto; text-align: center; margin-bottom: 10px;">';
  2465 	$out  = '<div style="width: 460px; margin: 0 auto; text-align: center; margin-bottom: 10px;">';
  2466   $out .= '<div style="float: left;">&larr; Deny</div>';
  2466 	$out .= '<div style="float: left;">&larr; Deny</div>';
  2467   $out .= '<div style="float: right;">Allow &rarr;</div>';
  2467 	$out .= '<div style="float: right;">Allow &rarr;</div>';
  2468   $out .= 'Neutral';
  2468 	$out .= 'Neutral';
  2469   $out .= '<div style="clear: both;"></div>';
  2469 	$out .= '<div style="clear: both;"></div>';
  2470   // 11 boxes on each side of the center
  2470 	// 11 boxes on each side of the center
  2471   $inc = ceil ( ( 0xFF - ACL_SCALE_MINIMAL_SHADE ) / 11 );
  2471 	$inc = ceil ( ( 0xFF - ACL_SCALE_MINIMAL_SHADE ) / 11 );
  2472   for ( $i = ACL_SCALE_MINIMAL_SHADE; $i <= 0xFF; $i+= $inc )
  2472 	for ( $i = ACL_SCALE_MINIMAL_SHADE; $i <= 0xFF; $i+= $inc )
  2473   {
  2473 	{
  2474     $octet = dechex($i);
  2474 		$octet = dechex($i);
  2475     $color = "ff$octet$octet";
  2475 		$color = "ff$octet$octet";
  2476     $out .= '<div style="background-color: #' . $color . '; float: left; width: 20px;">&nbsp;</div>';
  2476 		$out .= '<div style="background-color: #' . $color . '; float: left; width: 20px;">&nbsp;</div>';
  2477   }
  2477 	}
  2478   $out .= '<div style="background-color: #efefef; float: left; width: 20px;">&nbsp;</div>';
  2478 	$out .= '<div style="background-color: #efefef; float: left; width: 20px;">&nbsp;</div>';
  2479   for ( $i = 0xFF; $i >= ACL_SCALE_MINIMAL_SHADE; $i-= $inc )
  2479 	for ( $i = 0xFF; $i >= ACL_SCALE_MINIMAL_SHADE; $i-= $inc )
  2480   {
  2480 	{
  2481     $octet = dechex($i);
  2481 		$octet = dechex($i);
  2482     $color = "{$octet}ff{$octet}";
  2482 		$color = "{$octet}ff{$octet}";
  2483     $out .= '<div style="background-color: #' . $color . '; float: left; width: 20px;">&nbsp;</div>';
  2483 		$out .= '<div style="background-color: #' . $color . '; float: left; width: 20px;">&nbsp;</div>';
  2484   }
  2484 	}
  2485   $out .= '<div style="clear: both;"></div>';
  2485 	$out .= '<div style="clear: both;"></div>';
  2486   $out .= '<div style="float: left;">-100</div>';
  2486 	$out .= '<div style="float: left;">-100</div>';
  2487   $out .= '<div style="float: right;">+100</div>';
  2487 	$out .= '<div style="float: right;">+100</div>';
  2488   $out .= '0';
  2488 	$out .= '0';
  2489   $out .= '</div>';
  2489 	$out .= '</div>';
  2490   return $out;
  2490 	return $out;
  2491 }
  2491 }
  2492 
  2492 
  2493 /**
  2493 /**
  2494  * Gets the numerical score for the serialized form of an ACL rule
  2494  * Gets the numerical score for the serialized form of an ACL rule
  2495  */
  2495  */
  2496 
  2496 
  2497 function get_acl_rule_score($perms)
  2497 function get_acl_rule_score($perms)
  2498 {
  2498 {
  2499   global $db, $session, $paths, $template, $plugins; // Common objects
  2499 	global $db, $session, $paths, $template, $plugins; // Common objects
  2500   if ( is_string($perms) )
  2500 	if ( is_string($perms) )
  2501     $perms = $session->string_to_perm($perms);
  2501 		$perms = $session->string_to_perm($perms);
  2502   else if ( !is_array($perms) )
  2502 	else if ( !is_array($perms) )
  2503     return false;
  2503 		return false;
  2504   $score = 0;
  2504 	$score = 0;
  2505   foreach ( $perms as $item )
  2505 	foreach ( $perms as $item )
  2506   {
  2506 	{
  2507     switch ( $item )
  2507 		switch ( $item )
  2508     {
  2508 		{
  2509       case AUTH_ALLOW :
  2509 			case AUTH_ALLOW :
  2510         $inc = 2;
  2510 				$inc = 2;
  2511         break;
  2511 				break;
  2512       case AUTH_WIKIMODE:
  2512 			case AUTH_WIKIMODE:
  2513         $inc = 1;
  2513 				$inc = 1;
  2514         break;
  2514 				break;
  2515       case AUTH_DISALLOW:
  2515 			case AUTH_DISALLOW:
  2516         $inc = -1;
  2516 				$inc = -1;
  2517         break;
  2517 				break;
  2518       case AUTH_DENY:
  2518 			case AUTH_DENY:
  2519         $inc = -2;
  2519 				$inc = -2;
  2520         break;
  2520 				break;
  2521       default:
  2521 			default:
  2522         $inc = 0;
  2522 				$inc = 0;
  2523         break;
  2523 				break;
  2524     }
  2524 		}
  2525     $score += $inc;
  2525 		$score += $inc;
  2526   }
  2526 	}
  2527   // this is different from the beta; calculate highest score and
  2527 	// this is different from the beta; calculate highest score and
  2528   // get percentage to be fairer to smaller/less broad rules
  2528 	// get percentage to be fairer to smaller/less broad rules
  2529   $divisor = count($perms) * 2;
  2529 	$divisor = count($perms) * 2;
  2530   if ( $divisor == 0 )
  2530 	if ( $divisor == 0 )
  2531   {
  2531 	{
  2532     return 0;
  2532 		return 0;
  2533   }
  2533 	}
  2534   $score = 100 * ( $score / $divisor );
  2534 	$score = 100 * ( $score / $divisor );
  2535   return round($score);
  2535 	return round($score);
  2536 }
  2536 }
  2537 
  2537 
  2538 ?>
  2538 ?>