plugins/SpecialLog.php
changeset 1227 bdac73ed481e
parent 1081 745200a9cc2a
equal deleted inserted replaced
1226:de56132c008d 1227:bdac73ed481e
     1 <?php
     1 <?php
     2 /**!info**
     2 /**!info**
     3 {
     3 {
     4   "Plugin Name"  : "plugin_speciallog_title",
     4 	"Plugin Name"  : "plugin_speciallog_title",
     5   "Plugin URI"   : "http://enanocms.org/",
     5 	"Plugin URI"   : "http://enanocms.org/",
     6   "Description"  : "plugin_speciallog_desc",
     6 	"Description"  : "plugin_speciallog_desc",
     7   "Author"       : "Dan Fuhry",
     7 	"Author"       : "Dan Fuhry",
     8   "Version"      : "1.1.6",
     8 	"Version"      : "1.1.6",
     9   "Author URI"   : "http://enanocms.org/"
     9 	"Author URI"   : "http://enanocms.org/"
    10 }
    10 }
    11 **!*/
    11 **!*/
    12 
    12 
    13 /*
    13 /*
    14  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
    14  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
    21  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    21  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    22  */
    22  */
    23 
    23 
    24 function SpecialLog_paths_init()
    24 function SpecialLog_paths_init()
    25 {
    25 {
    26   register_special_page('Log', 'specialpage_log');
    26 	register_special_page('Log', 'specialpage_log');
    27 }
    27 }
    28 
    28 
    29 function page_Special_Log()
    29 function page_Special_Log()
    30 {
    30 {
    31   global $db, $session, $paths, $template, $plugins; // Common objects
    31 	global $db, $session, $paths, $template, $plugins; // Common objects
    32   global $lang;
    32 	global $lang;
    33   global $output;
    33 	global $output;
    34   
    34 	
    35   // FIXME: This doesn't currently prohibit viewing of aggregate logs that might include a page for which
    35 	// FIXME: This doesn't currently prohibit viewing of aggregate logs that might include a page for which
    36   // we don't have permission to view history. It does, however, block access if a list of pages is given
    36 	// we don't have permission to view history. It does, however, block access if a list of pages is given
    37   // and one of those doesn't allow history_view.
    37 	// and one of those doesn't allow history_view.
    38   
    38 	
    39   // FIXME: This is a real hack. We're trying to get permissions on a random non-existent article, which
    39 	// FIXME: This is a real hack. We're trying to get permissions on a random non-existent article, which
    40   // effectively forces calculation to occur based on site-wide permissions.
    40 	// effectively forces calculation to occur based on site-wide permissions.
    41   $pid = '';
    41 	$pid = '';
    42   for ( $i = 0; $i < 32; $i++ )
    42 	for ( $i = 0; $i < 32; $i++ )
    43   {
    43 	{
    44     $pid .= chr(mt_rand(32, 126));
    44 		$pid .= chr(mt_rand(32, 126));
    45   }
    45 	}
    46   $perms = $session->fetch_page_acl($pid, 'Article');
    46 	$perms = $session->fetch_page_acl($pid, 'Article');
    47   $perms_changed = false;
    47 	$perms_changed = false;
    48   
    48 	
    49   require_once(ENANO_ROOT . '/includes/log.php');
    49 	require_once(ENANO_ROOT . '/includes/log.php');
    50   $log = new LogDisplay();
    50 	$log = new LogDisplay();
    51   $page = 1;
    51 	$page = 1;
    52   $pagesize = 50;
    52 	$pagesize = 50;
    53   $fmt = 'full';
    53 	$fmt = 'full';
    54   
    54 	
    55   if ( $params = $paths->getAllParams() )
    55 	if ( $params = $paths->getAllParams() )
    56   {
    56 	{
    57     if ( $params === 'AddFilter' && !empty($_POST['type']) && !empty($_POST['value']) )
    57 		if ( $params === 'AddFilter' && !empty($_POST['type']) && !empty($_POST['value']) )
    58     {
    58 		{
    59       $type = $_POST['type'];
    59 			$type = $_POST['type'];
    60       if ( $type == 'within' )
    60 			if ( $type == 'within' )
    61         $value = strval(intval($_POST['value']['within'])) . $_POST['value']['withinunits'];
    61 				$value = strval(intval($_POST['value']['within'])) . $_POST['value']['withinunits'];
    62       else
    62 			else
    63         $value = $_POST['value'][$type];
    63 				$value = $_POST['value'][$type];
    64       
    64 			
    65       if ( !ctype_digit($value) )
    65 			if ( !ctype_digit($value) )
    66         $value = str_replace('/', '.2f', sanitize_page_id($value));
    66 				$value = str_replace('/', '.2f', sanitize_page_id($value));
    67       
    67 			
    68       if ( $value !== '0' && (empty($value) || ( $type == 'within' && intval($value) == 0 )) )
    68 			if ( $value !== '0' && (empty($value) || ( $type == 'within' && intval($value) == 0 )) )
    69       {
    69 			{
    70         $adderror = $lang->get('log_err_addfilter_field_empty');
    70 				$adderror = $lang->get('log_err_addfilter_field_empty');
    71       }
    71 			}
    72       else
    72 			else
    73       {
    73 			{
    74         $append = ( !empty($_POST['existing_filters']) ) ? "{$_POST['existing_filters']}/" : '';
    74 				$append = ( !empty($_POST['existing_filters']) ) ? "{$_POST['existing_filters']}/" : '';
    75         $url = makeUrlNS('Special', "Log/{$append}{$type}={$value}");
    75 				$url = makeUrlNS('Special', "Log/{$append}{$type}={$value}");
    76         
    76 				
    77         redirect($url, '', '', 0);
    77 				redirect($url, '', '', 0);
    78       }
    78 			}
    79     }
    79 		}
    80     $params = explode('/', $params);
    80 		$params = explode('/', $params);
    81     foreach ( $params as $i => $param )
    81 		foreach ( $params as $i => $param )
    82     {
    82 		{
    83       $param = str_replace('.2f', '/', dirtify_page_id($param));
    83 			$param = str_replace('.2f', '/', dirtify_page_id($param));
    84       if ( preg_match('/^([a-z]+)!?=(.+?)$/', $param, $match) )
    84 			if ( preg_match('/^([a-z]+)!?=(.+?)$/', $param, $match) )
    85       {
    85 			{
    86         $name =& $match[1];
    86 				$name =& $match[1];
    87         $value =& $match[2];
    87 				$value =& $match[2];
    88         switch($name)
    88 				switch($name)
    89         {
    89 				{
    90           case 'resultpage':
    90 					case 'resultpage':
    91             $page = intval($value);
    91 						$page = intval($value);
    92             break;
    92 						break;
    93           case 'size':
    93 					case 'size':
    94             $pagesize = intval($value);
    94 						$pagesize = intval($value);
    95             break;
    95 						break;
    96           case 'fmt':
    96 					case 'fmt':
    97             switch($value)
    97 						switch($value)
    98             {
    98 						{
    99               case 'barenaked':
    99 							case 'barenaked':
   100               case 'ajax':
   100 							case 'ajax':
   101                 $fmt = 'naked';
   101 								$fmt = 'naked';
   102                 $output = new Output_Naked();
   102 								$output = new Output_Naked();
   103                 break;
   103 								break;
   104             }
   104 						}
   105             break;
   105 						break;
   106           case 'page':
   106 					case 'page':
   107             // tolerate slashes
   107 						// tolerate slashes
   108             $j = $i;
   108 						$j = $i;
   109             while ( true )
   109 						while ( true )
   110             {
   110 						{
   111               if ( isset($params[++$j]) )
   111 							if ( isset($params[++$j]) )
   112               {
   112 							{
   113                 if ( preg_match('/^([a-z]+)!?=(.+?)$/', $params[$j]) )
   113 								if ( preg_match('/^([a-z]+)!?=(.+?)$/', $params[$j]) )
   114                   break;
   114 									break;
   115                 
   115 								
   116                 $value .= '/' . $params[$j];
   116 								$value .= '/' . $params[$j];
   117               }
   117 							}
   118               else
   118 							else
   119               {
   119 							{
   120                 break;
   120 								break;
   121               }
   121 							}
   122             }
   122 						}
   123             if ( get_class($perms) == 'sessionManager' )
   123 						if ( get_class($perms) == 'sessionManager' )
   124             {
   124 						{
   125               unset($perms);
   125 							unset($perms);
   126               list($pid, $ns) = RenderMan::strToPageID($value);
   126 							list($pid, $ns) = RenderMan::strToPageID($value);
   127               $perms = $session->fetch_page_acl($pid, $ns);
   127 							$perms = $session->fetch_page_acl($pid, $ns);
   128               if ( !$perms->get_permissions('history_view') )
   128 							if ( !$perms->get_permissions('history_view') )
   129               {
   129 							{
   130                 die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('log_err_access_denied') . '</p>');
   130 								die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('log_err_access_denied') . '</p>');
   131               }
   131 							}
   132             }
   132 						}
   133             // no break here on purpose
   133 						// no break here on purpose
   134           default:
   134 					default:
   135             try
   135 						try
   136             {
   136 						{
   137               $log->add_criterion($name, $value);
   137 							$log->add_criterion($name, $value);
   138             }
   138 						}
   139             catch ( Exception $e )
   139 						catch ( Exception $e )
   140             {
   140 						{
   141             }
   141 						}
   142             break;
   142 						break;
   143         }
   143 				}
   144       }
   144 			}
   145     }
   145 		}
   146   }
   146 	}
   147   if ( !$perms->get_permissions('history_view') )
   147 	if ( !$perms->get_permissions('history_view') )
   148   {
   148 	{
   149     die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('log_err_access_denied') . '</p>');
   149 		die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('log_err_access_denied') . '</p>');
   150   }
   150 	}
   151   
   151 	
   152   $page--;
   152 	$page--;
   153   $rowcount = $log->get_row_count();
   153 	$rowcount = $log->get_row_count();
   154   $paramsbit = rtrim(preg_replace('|/?resultpage=([0-9]+)/?|', '/', $paths->getAllParams()), '/');
   154 	$paramsbit = rtrim(preg_replace('|/?resultpage=([0-9]+)/?|', '/', $paths->getAllParams()), '/');
   155   $paramsbit = ( !empty($paramsbit) ) ? "/$paramsbit" : '';
   155 	$paramsbit = ( !empty($paramsbit) ) ? "/$paramsbit" : '';
   156   $result_url = makeUrlNS('Special', 'Log' . $paramsbit . '/resultpage=%s', false, true);
   156 	$result_url = makeUrlNS('Special', 'Log' . $paramsbit . '/resultpage=%s', false, true);
   157   $paginator = generate_paginator($page, ceil($rowcount / $pagesize), $result_url);
   157 	$paginator = generate_paginator($page, ceil($rowcount / $pagesize), $result_url);
   158   
   158 	
   159   $dataset = $log->get_data($page * $pagesize, $pagesize);
   159 	$dataset = $log->get_data($page * $pagesize, $pagesize);
   160   
   160 	
   161   $output->header();
   161 	$output->header();
   162   
   162 	
   163   // breadcrumbs
   163 	// breadcrumbs
   164   if ( $fmt != 'naked' )
   164 	if ( $fmt != 'naked' )
   165   {
   165 	{
   166     echo '<div class="breadcrumbs" style="font-weight: normal;" id="log-breadcrumbs">';
   166 		echo '<div class="breadcrumbs" style="font-weight: normal;" id="log-breadcrumbs">';
   167     echo speciallog_generate_breadcrumbs($log->get_criteria());
   167 		echo speciallog_generate_breadcrumbs($log->get_criteria());
   168     echo '</div>';
   168 		echo '</div>';
   169   
   169 	
   170   // form
   170 	// form
   171   ?>
   171 	?>
   172   
   172 	
   173   <!-- Begin filter add form -->
   173 	<!-- Begin filter add form -->
   174   
   174 	
   175   <form action="<?php echo makeUrlNS('Special', 'Log/AddFilter', false, true); ?>" method="post" enctype="multipart/form-data">
   175 	<form action="<?php echo makeUrlNS('Special', 'Log/AddFilter', false, true); ?>" method="post" enctype="multipart/form-data">
   176     <?php
   176 		<?php
   177     // serialize parameters
   177 		// serialize parameters
   178     $params_pre = rtrim(preg_replace('#/?resultpage=[0-9]+/?#', '/', $paths->getAllParams()), '/');
   178 		$params_pre = rtrim(preg_replace('#/?resultpage=[0-9]+/?#', '/', $paths->getAllParams()), '/');
   179     echo '<input type="hidden" name="existing_filters" value="' . htmlspecialchars($params_pre) . '" />';
   179 		echo '<input type="hidden" name="existing_filters" value="' . htmlspecialchars($params_pre) . '" />';
   180     ?>
   180 		?>
   181     <script type="text/javascript">//<![CDATA[
   181 		<script type="text/javascript">//<![CDATA[
   182       addOnloadHook(function()
   182 			addOnloadHook(function()
   183         {
   183 				{
   184           load_component('jquery');
   184 					load_component('jquery');
   185           $('#log_addfilter_select').change(function()
   185 					$('#log_addfilter_select').change(function()
   186             {
   186 						{
   187               var value = $(this).val();
   187 							var value = $(this).val();
   188               $('.log_addfilter').hide();
   188 							$('.log_addfilter').hide();
   189               $('#log_addform_' + value).show();
   189 							$('#log_addform_' + value).show();
   190             });
   190 						});
   191           $('#log_addform_' + $('#log_addfilter_select').val()).show();
   191 					$('#log_addform_' + $('#log_addfilter_select').val()).show();
   192         });
   192 				});
   193     // ]]>
   193 		// ]]>
   194     </script>
   194 		</script>
   195     <?php
   195 		<?php
   196     if ( isset($adderror) )
   196 		if ( isset($adderror) )
   197     {
   197 		{
   198       echo '<div class="error-box">' . $adderror . '</div>';
   198 			echo '<div class="error-box">' . $adderror . '</div>';
   199     }
   199 		}
   200     ?>
   200 		?>
   201     <div class="tblholder">
   201 		<div class="tblholder">
   202     <table border="0" cellspacing="1" cellpadding="4">
   202 		<table border="0" cellspacing="1" cellpadding="4">
   203       <tr>
   203 			<tr>
   204         <th colspan="2">
   204 				<th colspan="2">
   205           <?php echo $lang->get('log_heading_addfilter'); ?>
   205 					<?php echo $lang->get('log_heading_addfilter'); ?>
   206         </th>
   206 				</th>
   207       </tr>
   207 			</tr>
   208       <tr>
   208 			<tr>
   209       <td class="row1" style="width: 50%; text-align: right;">
   209 			<td class="row1" style="width: 50%; text-align: right;">
   210           <select name="type" id="log_addfilter_select">
   210 					<select name="type" id="log_addfilter_select">
   211             <option value="user"><?php echo $lang->get('log_form_filtertype_user'); ?></option>
   211 						<option value="user"><?php echo $lang->get('log_form_filtertype_user'); ?></option>
   212             <option value="page"><?php echo $lang->get('log_form_filtertype_page'); ?></option>
   212 						<option value="page"><?php echo $lang->get('log_form_filtertype_page'); ?></option>
   213             <option value="within"><?php echo $lang->get('log_form_filtertype_within'); ?></option>
   213 						<option value="within"><?php echo $lang->get('log_form_filtertype_within'); ?></option>
   214             <option value="action"><?php echo $lang->get('log_form_filtertype_action'); ?></option>
   214 						<option value="action"><?php echo $lang->get('log_form_filtertype_action'); ?></option>
   215             <option value="minor"><?php echo $lang->get('log_form_filtertype_minor'); ?></option>
   215 						<option value="minor"><?php echo $lang->get('log_form_filtertype_minor'); ?></option>
   216           </select>
   216 					</select>
   217         </td>
   217 				</td>
   218         <td class="row1" style="width: 50%; text-align: left;">
   218 				<td class="row1" style="width: 50%; text-align: left;">
   219           <div class="log_addfilter" id="log_addform_user">
   219 					<div class="log_addfilter" id="log_addform_user">
   220             <input type="text" class="autofill username" name="value[user]" size="40" />
   220 						<input type="text" class="autofill username" name="value[user]" size="40" />
   221           </div>
   221 					</div>
   222           <div class="log_addfilter" id="log_addform_page">
   222 					<div class="log_addfilter" id="log_addform_page">
   223             <input type="text" class="autofill page" name="value[page]" size="40" />
   223 						<input type="text" class="autofill page" name="value[page]" size="40" />
   224           </div>
   224 					</div>
   225           <div class="log_addfilter" id="log_addform_within">
   225 					<div class="log_addfilter" id="log_addform_within">
   226             <input type="text" name="value[within]" size="7" />
   226 						<input type="text" name="value[within]" size="7" />
   227             <select name="value[withinunits]">
   227 						<select name="value[withinunits]">
   228               <option value="d"><?php echo $lang->get('etc_unit_days'); ?></option>
   228 							<option value="d"><?php echo $lang->get('etc_unit_days'); ?></option>
   229               <option value="w"><?php echo $lang->get('etc_unit_weeks'); ?></option>
   229 							<option value="w"><?php echo $lang->get('etc_unit_weeks'); ?></option>
   230               <option value="m"><?php echo $lang->get('etc_unit_months'); ?></option>
   230 							<option value="m"><?php echo $lang->get('etc_unit_months'); ?></option>
   231               <option value="y"><?php echo $lang->get('etc_unit_years'); ?></option>
   231 							<option value="y"><?php echo $lang->get('etc_unit_years'); ?></option>
   232             </select>
   232 						</select>
   233           </div>
   233 					</div>
   234           <div class="log_addfilter" id="log_addform_action">
   234 					<div class="log_addfilter" id="log_addform_action">
   235             <select name="value[action]">
   235 						<select name="value[action]">
   236               <option value="rename"><?php echo $lang->get('log_formaction_rename'); ?></option>
   236 							<option value="rename"><?php echo $lang->get('log_formaction_rename'); ?></option>
   237               <option value="create"><?php echo $lang->get('log_formaction_create'); ?></option>
   237 							<option value="create"><?php echo $lang->get('log_formaction_create'); ?></option>
   238               <option value="delete"><?php echo $lang->get('log_formaction_delete'); ?></option>
   238 							<option value="delete"><?php echo $lang->get('log_formaction_delete'); ?></option>
   239               <option value="protect"><?php echo $lang->get('log_action_protect'); ?></option>
   239 							<option value="protect"><?php echo $lang->get('log_action_protect'); ?></option>
   240               <option value="edit"><?php echo $lang->get('log_action_edit'); ?></option>
   240 							<option value="edit"><?php echo $lang->get('log_action_edit'); ?></option>
   241               <option value="edit"><?php echo $lang->get('log_formaction_reupload'); ?></option>
   241 							<option value="edit"><?php echo $lang->get('log_formaction_reupload'); ?></option>
   242               <option value="edit"><?php echo $lang->get('log_formaction_votereset'); ?></option>
   242 							<option value="edit"><?php echo $lang->get('log_formaction_votereset'); ?></option>
   243             </select>
   243 						</select>
   244           </div>
   244 					</div>
   245           <div class="log_addfilter" id="log_addform_minor">
   245 					<div class="log_addfilter" id="log_addform_minor">
   246             <label>
   246 						<label>
   247               <input type="radio" name="value[minor]" value="1" checked="checked" />
   247 							<input type="radio" name="value[minor]" value="1" checked="checked" />
   248               <?php echo $lang->get('log_form_filtertype_minor_yes'); ?>
   248 							<?php echo $lang->get('log_form_filtertype_minor_yes'); ?>
   249             </label>
   249 						</label>
   250             <label>
   250 						<label>
   251               <input type="radio" name="value[minor]" value="0" />
   251 							<input type="radio" name="value[minor]" value="0" />
   252               <?php echo $lang->get('log_form_filtertype_minor_no'); ?>
   252 							<?php echo $lang->get('log_form_filtertype_minor_no'); ?>
   253             </label>
   253 						</label>
   254           </div>
   254 					</div>
   255         </td>
   255 				</td>
   256       </tr>
   256 			</tr>
   257       <tr>
   257 			<tr>
   258         <th colspan="2" class="subhead">
   258 				<th colspan="2" class="subhead">
   259           <input type="submit" value="<?php echo $lang->get('log_btn_add_filter'); ?>" />
   259 					<input type="submit" value="<?php echo $lang->get('log_btn_add_filter'); ?>" />
   260         </th>
   260 				</th>
   261       </tr>
   261 			</tr>
   262     </table>
   262 		</table>
   263     </div>
   263 		</div>
   264   
   264 	
   265   </form>
   265 	</form>
   266   
   266 	
   267   <!-- End filter add form -->
   267 	<!-- End filter add form -->
   268   
   268 	
   269   <?php
   269 	<?php
   270   
   270 	
   271   }
   271 	}
   272   
   272 	
   273   // start of actual log output area
   273 	// start of actual log output area
   274   if ( $fmt != 'naked' )
   274 	if ( $fmt != 'naked' )
   275   {
   275 	{
   276     echo '<div id="log-body">';
   276 		echo '<div id="log-body">';
   277   }
   277 	}
   278   
   278 	
   279   if ( $rowcount > 0 )
   279 	if ( $rowcount > 0 )
   280   {
   280 	{
   281     // we have some results, show pagination + result list
   281 		// we have some results, show pagination + result list
   282     echo '<h3 style="float: left;">' . $lang->get('log_heading_logdisplay') . '</h3>';
   282 		echo '<h3 style="float: left;">' . $lang->get('log_heading_logdisplay') . '</h3>';
   283     
   283 		
   284     echo $paginator;
   284 		echo $paginator;
   285     // padding
   285 		// padding
   286     echo '<div style="height: 10px; clear: both;"></div>';
   286 		echo '<div style="height: 10px; clear: both;"></div>';
   287     foreach ( $dataset as $row )
   287 		foreach ( $dataset as $row )
   288     {
   288 		{
   289       echo LogDisplay::render_row($row) . '<br />';
   289 			echo LogDisplay::render_row($row) . '<br />';
   290     }
   290 		}
   291     echo $paginator;
   291 		echo $paginator;
   292   }
   292 	}
   293   else
   293 	else
   294   {
   294 	{
   295     // no results
   295 		// no results
   296     echo '<h2 class="emptymessage">' . $lang->get('log_msg_no_results') . '</h2>';
   296 		echo '<h2 class="emptymessage">' . $lang->get('log_msg_no_results') . '</h2>';
   297   }
   297 	}
   298   
   298 	
   299   if ( $fmt != 'naked' )
   299 	if ( $fmt != 'naked' )
   300     echo '</div> <!-- div#log-body -->';
   300 		echo '</div> <!-- div#log-body -->';
   301   
   301 	
   302   $output->footer();
   302 	$output->footer();
   303 }
   303 }
   304 
   304 
   305 function speciallog_generate_breadcrumbs($criteria)
   305 function speciallog_generate_breadcrumbs($criteria)
   306 {
   306 {
   307   global $db, $session, $paths, $template, $plugins; // Common objects
   307 	global $db, $session, $paths, $template, $plugins; // Common objects
   308   global $lang;
   308 	global $lang;
   309   
   309 	
   310   if ( count($criteria) == 0 )
   310 	if ( count($criteria) == 0 )
   311   {
   311 	{
   312     return $lang->get('log_msg_no_filters');
   312 		return $lang->get('log_msg_no_filters');
   313   }
   313 	}
   314   
   314 	
   315   $html = array();
   315 	$html = array();
   316   foreach ( $criteria as $criterion )
   316 	foreach ( $criteria as $criterion )
   317   {
   317 	{
   318     list($type, $value) = $criterion;
   318 		list($type, $value) = $criterion;
   319     switch($type)
   319 		switch($type)
   320     {
   320 		{
   321       case 'user':
   321 			case 'user':
   322         $rank_info = $session->get_user_rank($value);
   322 				$rank_info = $session->get_user_rank($value);
   323         $user_link = '<a href="' . makeUrlNS('User', $value, false, true) . '" style="' . $rank_info['rank_style'] . '" title="' . htmlspecialchars($lang->get($rank_info['rank_title'])) . '">';
   323 				$user_link = '<a href="' . makeUrlNS('User', $value, false, true) . '" style="' . $rank_info['rank_style'] . '" title="' . htmlspecialchars($lang->get($rank_info['rank_title'])) . '">';
   324         $user_link .= htmlspecialchars(str_replace('_', ' ', $value)) . '</a>';
   324 				$user_link .= htmlspecialchars(str_replace('_', ' ', $value)) . '</a>';
   325         
   325 				
   326         $crumb = $lang->get('log_breadcrumb_author', array('user' => $user_link));
   326 				$crumb = $lang->get('log_breadcrumb_author', array('user' => $user_link));
   327         break;
   327 				break;
   328       case 'page':
   328 			case 'page':
   329         list($pid, $ns) = RenderMan::strToPageID($value);
   329 				list($pid, $ns) = RenderMan::strToPageID($value);
   330         $ns = namespace_factory($pid, $ns);
   330 				$ns = namespace_factory($pid, $ns);
   331         $exist = $ns->exists() ? '' : ' class="wikilink-nonexistent"';
   331 				$exist = $ns->exists() ? '' : ' class="wikilink-nonexistent"';
   332         $crumb = $lang->get('log_breadcrumb_page', array('page' => '<a' . $exist . ' href="' . makeUrl($value, false, true) . '">' . htmlspecialchars($ns->title) . '</a>'));
   332 				$crumb = $lang->get('log_breadcrumb_page', array('page' => '<a' . $exist . ' href="' . makeUrl($value, false, true) . '">' . htmlspecialchars($ns->title) . '</a>'));
   333         break;
   333 				break;
   334       case 'action':
   334 			case 'action':
   335         $action = ( $lang->get("log_formaction_{$value}") === "log_formaction_{$value}" ) ? $lang->get("log_action_{$value}") : $lang->get("log_formaction_{$value}");
   335 				$action = ( $lang->get("log_formaction_{$value}") === "log_formaction_{$value}" ) ? $lang->get("log_action_{$value}") : $lang->get("log_formaction_{$value}");
   336         $crumb = $lang->get('log_breadcrumb_action', array('action' => htmlspecialchars($action)));
   336 				$crumb = $lang->get('log_breadcrumb_action', array('action' => htmlspecialchars($action)));
   337         break;
   337 				break;
   338       case 'minor':
   338 			case 'minor':
   339         $crumb = $value == '1' ? $lang->get('log_form_filtertype_minor_yes') : $lang->get('log_form_filtertype_minor_no');
   339 				$crumb = $value == '1' ? $lang->get('log_form_filtertype_minor_yes') : $lang->get('log_form_filtertype_minor_no');
   340         break;
   340 				break;
   341       case 'within':
   341 			case 'within':
   342         $value = intval($value);
   342 				$value = intval($value);
   343         if ( $value % 31536000 == 0 )
   343 				if ( $value % 31536000 == 0 )
   344         {
   344 				{
   345           $n = $value / 31536000;
   345 					$n = $value / 31536000;
   346           $value = "$n " . $lang->get( $n > 1 ? 'etc_unit_years' : 'etc_unit_year' );
   346 					$value = "$n " . $lang->get( $n > 1 ? 'etc_unit_years' : 'etc_unit_year' );
   347         }
   347 				}
   348         else if ( $value % 2592000 == 0 )
   348 				else if ( $value % 2592000 == 0 )
   349         {
   349 				{
   350           $n = $value / 2592000;
   350 					$n = $value / 2592000;
   351           $value = "$n " . $lang->get( $n > 1 ? 'etc_unit_months' : 'etc_unit_month' );
   351 					$value = "$n " . $lang->get( $n > 1 ? 'etc_unit_months' : 'etc_unit_month' );
   352         }
   352 				}
   353         else if ( $value % 604800 == 0 )
   353 				else if ( $value % 604800 == 0 )
   354         {
   354 				{
   355           $n = $value / 604800;
   355 					$n = $value / 604800;
   356           $value = "$n " . $lang->get( $n > 1 ? 'etc_unit_weeks' : 'etc_unit_week' );
   356 					$value = "$n " . $lang->get( $n > 1 ? 'etc_unit_weeks' : 'etc_unit_week' );
   357         }
   357 				}
   358         else if ( $value % 86400 == 0 )
   358 				else if ( $value % 86400 == 0 )
   359         {
   359 				{
   360           $n = $value / 86400;
   360 					$n = $value / 86400;
   361           $value = "$n " . $lang->get( $n > 1 ? 'etc_unit_days' : 'etc_unit_day' );
   361 					$value = "$n " . $lang->get( $n > 1 ? 'etc_unit_days' : 'etc_unit_day' );
   362         }
   362 				}
   363         else
   363 				else
   364         {
   364 				{
   365           $value = "$value " . $lang->get( $value > 1 ? 'etc_unit_seconds' : 'etc_unit_second' );
   365 					$value = "$value " . $lang->get( $value > 1 ? 'etc_unit_seconds' : 'etc_unit_second' );
   366         }
   366 				}
   367         $crumb = $lang->get('log_breadcrumb_within', array('time' => $value));
   367 				$crumb = $lang->get('log_breadcrumb_within', array('time' => $value));
   368         break;
   368 				break;
   369     }
   369 		}
   370     $html[] = $crumb . ' ' . speciallog_crumb_remove_link($criterion);
   370 		$html[] = $crumb . ' ' . speciallog_crumb_remove_link($criterion);
   371   }
   371 	}
   372   return implode(' &raquo; ', $html);
   372 	return implode(' &raquo; ', $html);
   373 }
   373 }
   374 
   374 
   375 function speciallog_crumb_remove_link($criterion)
   375 function speciallog_crumb_remove_link($criterion)
   376 {
   376 {
   377   global $db, $session, $paths, $template, $plugins; // Common objects
   377 	global $db, $session, $paths, $template, $plugins; // Common objects
   378   global $lang;
   378 	global $lang;
   379   
   379 	
   380   list($type, $value) = $criterion;
   380 	list($type, $value) = $criterion;
   381   
   381 	
   382   $params = explode('/', dirtify_page_id($paths->getAllParams()));
   382 	$params = explode('/', dirtify_page_id($paths->getAllParams()));
   383   foreach ( $params as $i => $param )
   383 	foreach ( $params as $i => $param )
   384   {
   384 	{
   385     if ( $param === "$type=$value" )
   385 		if ( $param === "$type=$value" )
   386     {
   386 		{
   387       unset($params[$i]);
   387 			unset($params[$i]);
   388       break;
   388 			break;
   389     }
   389 		}
   390     else if ( $type === 'within' )
   390 		else if ( $type === 'within' )
   391     {
   391 		{
   392       list($ptype, $pvalue) = explode('=', $param);
   392 			list($ptype, $pvalue) = explode('=', $param);
   393       if ( $ptype !== 'within' )
   393 			if ( $ptype !== 'within' )
   394         continue;
   394 				continue;
   395       
   395 			
   396       $lastchar = substr($pvalue, -1);
   396 			$lastchar = substr($pvalue, -1);
   397       $amt = intval($pvalue);
   397 			$amt = intval($pvalue);
   398       switch($lastchar)
   398 			switch($lastchar)
   399       {
   399 			{
   400         case 'd':
   400 				case 'd':
   401           $amt = $amt * 86400;
   401 					$amt = $amt * 86400;
   402           break;
   402 					break;
   403         case 'w':
   403 				case 'w':
   404           $amt = $amt * 604800;
   404 					$amt = $amt * 604800;
   405           break;
   405 					break;
   406         case 'm':
   406 				case 'm':
   407           $amt = $amt * 2592000;
   407 					$amt = $amt * 2592000;
   408           break;
   408 					break;
   409         case 'y':
   409 				case 'y':
   410           $amt = $amt * 31536000;
   410 					$amt = $amt * 31536000;
   411           break;
   411 					break;
   412       }
   412 			}
   413       if ( $amt === $value )
   413 			if ( $amt === $value )
   414       {
   414 			{
   415         unset($params[$i]);
   415 				unset($params[$i]);
   416         break;
   416 				break;
   417       }
   417 			}
   418     }
   418 		}
   419   }
   419 	}
   420   if ( count($params) > 0 )
   420 	if ( count($params) > 0 )
   421   {
   421 	{
   422     $params = implode('/', $params);
   422 		$params = implode('/', $params);
   423     $url = makeUrlNS('Special', "Log/$params", false, true);
   423 		$url = makeUrlNS('Special', "Log/$params", false, true);
   424   }
   424 	}
   425   else
   425 	else
   426   {
   426 	{
   427     $url = makeUrlNS('Special', "Log", false, true);
   427 		$url = makeUrlNS('Special', "Log", false, true);
   428   }
   428 	}
   429   
   429 	
   430   return '<sup><a href="' . $url . '">(x)</a></sup>';
   430 	return '<sup><a href="' . $url . '">(x)</a></sup>';
   431 }
   431 }