Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'manage-config' into master-1.2.x

This branch implements several improvements to the Manage Configuration
page, including:

 - better performance
 - filtering
 - ability to edit config options
  • Loading branch information...
commit e539dd68df6b5efa79869ba8f6a0427fb5aa7835 2 parents 0052435 + d000c4d
@dregad dregad authored
View
348 adm_config_report.php
@@ -32,35 +32,42 @@
print_manage_menu( 'adm_config_report.php' );
print_manage_config_menu( 'adm_config_report.php' );
+ $t_config_types = array(
+ CONFIG_TYPE_DEFAULT => 'default',
+ CONFIG_TYPE_INT => 'integer',
+ CONFIG_TYPE_FLOAT => 'float',
+ CONFIG_TYPE_COMPLEX => 'complex',
+ CONFIG_TYPE_STRING => 'string',
+ );
+
function get_config_type( $p_type ) {
- switch( $p_type ) {
- case CONFIG_TYPE_INT:
- return "integer";
- case CONFIG_TYPE_FLOAT:
- return "float";
- case CONFIG_TYPE_COMPLEX:
- return "complex";
- case CONFIG_TYPE_STRING:
- default:
- return "string";
+ global $t_config_types;
+
+ if( array_key_exists( $p_type, $t_config_types ) ) {
+ return $t_config_types[$p_type];
+ } else {
+ return $t_config_types[CONFIG_TYPE_DEFAULT];
}
}
- function print_config_value_as_string( $p_type, $p_value ) {
+ function print_config_value_as_string( $p_type, $p_value, $p_for_display = true ) {
$t_corrupted = false;
switch( $p_type ) {
+ case CONFIG_TYPE_DEFAULT:
+ return;
case CONFIG_TYPE_FLOAT:
- $t_value = (float)$p_value;
- echo $t_value;
+ echo (float)$p_value;
return;
case CONFIG_TYPE_INT:
- $t_value = (integer)$p_value;
- echo $t_value;
+ echo (integer)$p_value;
return;
case CONFIG_TYPE_STRING:
$t_value = config_eval( $p_value );
- echo string_nl2br( string_html_specialchars( "'$t_value'" ) );
+ if( $p_for_display ) {
+ $t_value = "'$t_value'";
+ }
+ echo string_nl2br( string_html_specialchars( $t_value ) );
return;
case CONFIG_TYPE_COMPLEX:
$t_value = @unserialize( $p_value );
@@ -73,27 +80,223 @@ function print_config_value_as_string( $p_type, $p_value ) {
break;
}
- echo '<pre>';
+ if( $t_corrupted ) {
+ $t_output = $p_for_display ? lang_get( 'configuration_corrupted' ) : '';
+ } else {
+ $t_output = var_export( $t_value, true );
+ }
- if ( $t_corrupted ) {
- echo lang_get( 'configuration_corrupted' );
+ if( $p_for_display ) {
+ echo "<pre>$t_output</pre>";
} else {
- if ( function_exists( 'var_export' ) ) {
- var_export( $t_value );
- } else {
- print_r( $t_value );
+ echo $t_output;
+ }
+ }
+
+ function print_option_list_from_array( $p_array, $p_filter_value ) {
+ foreach( $p_array as $t_key => $t_value ) {
+ echo "<option value='$t_key'";
+ check_selected( $p_filter_value, $t_key );
+ echo ">$t_value</option>\n";
+ }
+ }
+
+ # Get filter values
+ $t_filter_save = gpc_get_bool( 'save' );
+ $t_filter_default = gpc_get_bool( 'default_filter_button', false );
+ $t_filter_reset = gpc_get_bool( 'reset_filter_button', false );
+ if( $t_filter_default ) {
+ $t_filter_user_value = ALL_USERS;
+ $t_filter_project_value = ALL_PROJECTS;
+ $t_filter_config_value = META_FILTER_NONE;
+ } else if( $t_filter_reset ) {
+ $t_filter_user_value = META_FILTER_NONE;
+ $t_filter_project_value = META_FILTER_NONE;
+ $t_filter_config_value = META_FILTER_NONE;
+ } else {
+ $t_filter_user_value = gpc_get_int( 'filter_user_id', ALL_USERS );
+ $t_filter_project_value = gpc_get_int( 'filter_project_id', ALL_PROJECTS );
+ $t_filter_config_value = gpc_get_string( 'filter_config_id', META_FILTER_NONE );
+ }
+
+ # Manage filter's persistency through cookie
+ $t_cookie_name = config_get( 'manage_config_cookie' );
+ if( $t_filter_save ) {
+ # Save user's filter to the cookie
+ $t_cookie_string = implode(
+ ':',
+ array(
+ $t_filter_user_value,
+ $t_filter_project_value,
+ $t_filter_config_value,
+ )
+ );
+ gpc_set_cookie( $t_cookie_name, $t_cookie_string, true );
+ } else {
+ # Retrieve the filter from the cookie if it exists
+ $t_cookie_string = gpc_get_cookie( $t_cookie_name, null );
+ if( null !== $t_cookie_string ) {
+ $t_cookie_contents = explode( ':', $t_cookie_string );
+
+ $t_filter_user_value = $t_cookie_contents[0];
+ $t_filter_project_value = $t_cookie_contents[1];
+ $t_filter_config_value = $t_cookie_contents[2];
+
+ if( $t_filter_project_value != META_FILTER_NONE && project_exists( $t_filter_project_value ) ) {
+ $t_filter_project_value = ALL_PROJECTS;
}
}
+ }
+
+ # Get config edit values
+ $t_edit_user_id = gpc_get_int( 'user_id', $t_filter_user_value == META_FILTER_NONE ? ALL_USERS : $t_filter_user_value );
+ $t_edit_project_id = gpc_get_int( 'project_id', $t_filter_project_value == META_FILTER_NONE ? ALL_PROJECTS : $t_filter_project_value );
+ $t_edit_option = gpc_get_string( 'config_option', $t_filter_config_value == META_FILTER_NONE ? '' : $t_filter_config_value );
+ $t_edit_type = gpc_get_string( 'type', CONFIG_TYPE_DEFAULT );
+ $t_edit_value = gpc_get_string( 'value', '' );
+
+ # Apply filters
+ $t_config_table = db_get_table( 'mantis_config_table' );
+ $t_project_table = db_get_table( 'mantis_project_table' );
+
+ # Get users in db having specific configs
+ $query = "SELECT DISTINCT user_id
+ FROM $t_config_table
+ WHERE user_id <> " . db_param() ;
+ $t_result = db_query_bound( $query, array( ALL_USERS ) );
+ if( $t_filter_user_value != META_FILTER_NONE && $t_filter_user_value != ALL_USERS ) {
+ # Make sure the filter value exists in the list
+ $t_users_list[$t_filter_user_value] = user_get_name( $t_filter_user_value );
+ } else {
+ $t_users_list = array();
+ }
+ while ( $row = db_fetch_array( $t_result ) ) {
+ $t_user_id = $row['user_id'];
+ $t_users_list[$t_user_id] = user_get_name( $t_user_id );
+ }
+ asort( $t_users_list );
+ # Prepend '[any]' and 'All Users' to the list
+ $t_users_list = array(
+ META_FILTER_NONE => '[' . lang_get( 'any' ) . ']',
+ ALL_USERS => lang_get( 'all_users' ),
+ )
+ + $t_users_list;
+
+ # Get projects in db with specific configs
+ $query = "SELECT DISTINCT project_id, pt.name as project_name
+ FROM $t_config_table as ct
+ JOIN $t_project_table as pt ON pt.id = ct.project_id
+ WHERE project_id!=0
+ ORDER BY project_name";
+ $t_result = db_query_bound( $query );
+ $t_projects_list[META_FILTER_NONE] = '[' . lang_get( 'any' ) . ']';
+ $t_projects_list[ALL_PROJECTS] = lang_get( 'all_projects' );
+ while ( $row = db_fetch_array( $t_result ) ) {
+ extract( $row, EXTR_PREFIX_ALL, 'v' );
+ $t_projects_list[$v_project_id] = $v_project_name;
+ }
+
+ # Get config list used in db
+ $query = "SELECT DISTINCT config_id
+ FROM $t_config_table
+ ORDER BY config_id";
+ $t_result = db_query_bound( $query );
+ $t_configs_list[META_FILTER_NONE] = '[' . lang_get( 'any' ) . ']';
+ if( $t_filter_config_value != META_FILTER_NONE ) {
+ # Make sure the filter value exists in the list
+ $t_configs_list[$t_filter_config_value] = $t_filter_config_value;
+ }
+ while ( $row = db_fetch_array( $t_result ) ) {
+ extract( $row, EXTR_PREFIX_ALL, 'v' );
+ $t_configs_list[$v_config_id] = $v_config_id;
+ }
- echo '</pre>';
+ # Build filter's where clause
+ $t_where = '';
+ if( $t_filter_user_value != META_FILTER_NONE ) {
+ $t_where .= " AND user_id = $t_filter_user_value ";
+ }
+ if( $t_filter_project_value != META_FILTER_NONE ) {
+ $t_where .= " AND project_id = $t_filter_project_value ";
+ }
+ if( $t_filter_config_value != META_FILTER_NONE ) {
+ $t_where .= " AND config_id = '$t_filter_config_value' ";
+ }
+ if( $t_where != '' ) {
+ $t_where = " WHERE 1=1 " . $t_where;
}
- $t_config_table = db_get_table( 'mantis_config_table' );
- $query = "SELECT config_id, user_id, project_id, type, value, access_reqd FROM $t_config_table ORDER BY user_id, project_id, config_id";
+ $query = "SELECT config_id, user_id, project_id, type, value, access_reqd
+ FROM $t_config_table
+ $t_where
+ ORDER BY user_id, project_id, config_id ";
$result = db_query_bound( $query );
?>
+
<br />
<div align="center">
+
+<!-- FILTER FORM -->
+<form id="filter_form" method="post">
+<?php # CSRF protection not required here - form does not result in modifications ?>
+ <input type="hidden" name="save" value="1" />
+
+<table class="width100" cellspacing="1">
+ <!-- Title -->
+ <tr>
+ <td class="form-title" colspan="7">
+ <?php echo lang_get( 'filters' ) ?>
+ </td>
+ </tr>
+
+ <tr class="row-category2">
+ <td class="small-caption">
+ <?php echo lang_get( 'username' ); ?>: <br />
+ </td>
+ <td class="small-caption">
+ <?php echo lang_get( 'project_name' ); ?>: <br />
+ </td>
+ <td class="small-caption">
+ <?php echo lang_get( 'configuration_option' ); ?>: <br />
+ </td>
+ </tr>
+
+ <tr class="row-1">
+ <td>
+ <select name="filter_user_id">
+ <?php
+ print_option_list_from_array( $t_users_list, $t_filter_user_value );
+ ?>
+ </select>
+ </td>
+ <td>
+ <select name="filter_project_id">
+ <?php
+ print_option_list_from_array( $t_projects_list, $t_filter_project_value );
+ ?>
+ </select>
+ </td>
+ <td>
+ <select name="filter_config_id">
+ <?php
+ print_option_list_from_array( $t_configs_list, $t_filter_config_value );
+ ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <input name="apply_filter_button" type="submit" class="button-small" value="<?php echo lang_get( 'filter_button' )?>" />
+ <input name="default_filter_button" type="submit" class="button-small" value="<?php echo lang_get( 'default_filter' )?>" />
+ <input name="reset_filter_button" type="submit" class="button-small" value="<?php echo lang_get( 'reset_query' )?>" />
+ </td>
+ </tr>
+</table>
+</form>
+
+<br />
+
+<!-- CONFIGURATIONS LIST -->
<table class="width100" cellspacing="1">
<!-- Title -->
@@ -126,6 +329,10 @@ function print_config_value_as_string( $p_type, $p_value ) {
</td>
</tr>
<?php
+ # Pre-generate a form security token to avoid performance issues when the
+ # db contains a large number of configurations
+ $t_form_security_token = form_security_token( 'adm_config_delete' );
+
while ( $row = db_fetch_array( $result ) ) {
extract( $row, EXTR_PREFIX_ALL, 'v' );
@@ -152,8 +359,35 @@ function print_config_value_as_string( $p_type, $p_value ) {
</td>
<td class="center">
<?php
- if ( config_can_delete( $v_config_id ) ) {
- print_button( "adm_config_delete.php?user_id=$v_user_id&project_id=$v_project_id&config_option=$v_config_id", lang_get( 'delete_link' ) );
+ if (
+ config_can_delete( $v_config_id )
+ && access_has_global_level( config_get( 'set_configuration_threshold' ) )
+ ) {
+ # Update button (will populate edit form at page bottom)
+ print_button(
+ '#config_set_form',
+ lang_get( 'edit_link' ),
+ array(
+ 'user_id' => $v_user_id,
+ 'project_id' => $v_project_id,
+ 'config_option' => $v_config_id,
+ 'type' => $v_type,
+ 'value' => $v_value,
+ ),
+ OFF
+ );
+
+ # Delete button
+ print_button(
+ 'adm_config_delete.php',
+ lang_get( 'delete_link' ),
+ array(
+ 'user_id' => $v_user_id,
+ 'project_id' => $v_project_id,
+ 'config_option' => $v_config_id,
+ ),
+ $t_form_security_token
+ );
} else {
echo '&#160;';
}
@@ -164,12 +398,17 @@ function print_config_value_as_string( $p_type, $p_value ) {
} # end for loop
?>
</table>
+
+
<?php
- if ( access_has_global_level( config_get('set_configuration_threshold' ) ) ) {
+ # Only display the edit form if user is authorized to change configuration
+ if ( access_has_global_level( config_get( 'set_configuration_threshold' ) ) ) {
?>
<br />
+
<!-- Config Set Form -->
-<form method="post" action="adm_config_set.php">
+
+<form id="config_set_form" method="post" action="adm_config_set.php">
<?php echo form_security_field( 'adm_config_set' ) ?>
<table class="width100" cellspacing="1">
@@ -179,67 +418,94 @@ function print_config_value_as_string( $p_type, $p_value ) {
<?php echo lang_get( 'set_configuration_option' ) ?>
</td>
</tr>
+
+<!-- Username -->
<tr <?php echo helper_alternate_class() ?> valign="top">
<td>
<?php echo lang_get( 'username' ) ?>
</td>
<td>
<select name="user_id">
- <option value="0" selected="selected"><?php echo lang_get( 'all_users' ); ?></option>
- <?php print_user_option_list( auth_get_current_user_id() ) ?>
+ <option value="<?php echo ALL_USERS; ?>"
+ <?php check_selected( $t_edit_user_id, ALL_USERS ) ?>>
+ <?php echo lang_get( 'all_users' ); ?>
+ </option>
+ <?php print_user_option_list( $t_edit_user_id ) ?>
</select>
</td>
</tr>
+
+<!-- Project -->
<tr <?php echo helper_alternate_class() ?> valign="top">
<td>
<?php echo lang_get( 'project_name' ) ?>
</td>
<td>
<select name="project_id">
- <option value="0" selected="selected"><?php echo lang_get( 'all_projects' ); ?></option>
- <?php print_project_option_list( ALL_PROJECTS, false ) ?>
+ <option value="<?php echo ALL_PROJECTS; ?>"
+ <?php check_selected( $t_edit_project_id, ALL_PROJECTS ); ?>>
+ <?php echo lang_get( 'all_projects' ); ?>
+ </option>
+ <?php print_project_option_list( $t_edit_project_id, false ) ?>
</select>
</td>
</tr>
+
+<!-- Config option name -->
<tr <?php echo helper_alternate_class() ?> valign="top">
<td>
<?php echo lang_get( 'configuration_option' ) ?>
</td>
<td>
- <input type="text" name="config_option" value="" size="64" maxlength="64" />
+ <input type="text" name="config_option"
+ value="<?php echo $t_edit_option; ?>"
+ size="64" maxlength="64" />
</td>
</tr>
+
+<!-- Option type -->
<tr <?php echo helper_alternate_class() ?> valign="top">
<td>
<?php echo lang_get( 'configuration_option_type' ) ?>
</td>
<td>
<select name="type">
- <option value="default" selected="selected">default</option>
- <option value="string">string</option>
- <option value="integer">integer</option>
- <option value="complex">complex</option>
+ <?php
+ foreach( $t_config_types as $t_key => $t_type ) {
+ echo '<option value="' . $t_key . '" ';
+ check_selected( $t_key, $t_edit_type );
+ echo ">$t_type</option>";
+ }
+ ?>
</select>
</td>
</tr>
+
+<!-- Option Value -->
<tr <?php echo helper_alternate_class() ?> valign="top">
<td>
<?php echo lang_get( 'configuration_option_value' ) ?>
</td>
<td>
- <textarea name="value" cols="80" rows="10"></textarea>
+ <textarea name="value" cols="80" rows="10"><?php
+ echo print_config_value_as_string( $t_edit_type, $t_edit_value, false );
+ ?></textarea>
</td>
</tr>
+
<tr>
<td colspan="2">
- <input type="submit" name="config_set" class="button" value="<?php echo lang_get( 'set_configuration_option' ) ?>" />
+ <input type="submit" name="config_set" class="button" value="<?php echo lang_get( 'set_configuration_option' ) ?>" />
</td>
</tr>
+
</table>
</form>
+
<?php
} # end user can change config
?>
</div>
+
<?php
html_page_bottom();
View
212 adm_config_set.php
@@ -29,11 +29,11 @@
form_security_validate( 'adm_config_set' );
- $f_user_id = gpc_get_int( 'user_id' );
- $f_project_id = gpc_get_int( 'project_id' );
+ $f_user_id = gpc_get_int( 'user_id' );
+ $f_project_id = gpc_get_int( 'project_id' );
$f_config_option = gpc_get_string( 'config_option' );
- $f_type = gpc_get_string( 'type' );
- $f_value = gpc_get_string( 'value' );
+ $f_type = gpc_get_string( 'type' );
+ $f_value = gpc_get_string( 'value' );
if ( is_blank( $f_config_option ) ) {
error_parameters( 'config_option' );
@@ -60,52 +60,38 @@
trigger_error( ERROR_CONFIG_OPT_CANT_BE_SET_IN_DB, ERROR );
}
- if ( $f_type === 'default' ) {
+ # For 'default', behavior is based on the global variable's type
+ if( $f_type == CONFIG_TYPE_DEFAULT ) {
$t_config_global_value = config_get_global( $f_config_option );
- if ( is_string( $t_config_global_value ) ) {
- $t_type = 'string';
- } else if ( is_int( $t_config_global_value ) ) {
- $t_type = 'integer';
- } else { # note that we consider bool and float as complex. We use ON/OFF for bools which map to numeric.
- $t_type = 'complex';
+ if( is_string( $t_config_global_value ) ) {
+ $t_type = CONFIG_TYPE_STRING;
+ } else if( is_int( $t_config_global_value ) ) {
+ $t_type = CONFIG_TYPE_INT;
+ } else if( is_float( $t_config_global_value ) ) {
+ $t_type = CONFIG_TYPE_FLOAT;
+ } else {
+ # note that we consider bool and float as complex.
+ # We use ON/OFF for bools which map to numeric.
+ $t_type = CONFIG_TYPE_COMPLEX;
}
} else {
$t_type = $f_type;
}
- if ( $t_type === 'string' ) {
- $t_value = $f_value;
- } else if ( $t_type === 'integer' ) {
- $t_value = (integer)$f_value;
- } else {
- # We support these kind of variables here:
- # 1. constant values (like the ON/OFF switches): they are defined as constants mapping to numeric values
- # 2. simple arrays with the form: array( a, b, c, d )
- # 3. associative arrays with the form: array( a=>1, b=>2, c=>3, d=>4 )
- # TODO: allow multi-dimensional arrays, allow commas and => within strings
- $t_full_string = trim( $f_value );
- if ( preg_match('/array[\s]*\((.*)\)/s', $t_full_string, $t_match ) === 1 ) {
- // we have an array here
- $t_values = explode( ',', trim( $t_match[1] ) );
- foreach ( $t_values as $key => $value ) {
- if ( !trim( $value ) ) {
- continue;
- }
- $t_split = explode( '=>', $value, 2 );
- if ( count( $t_split ) == 2 ) {
- // associative array
- $t_new_key = constant_replace( trim( $t_split[0], " \t\n\r\0\x0B\"'" ) );
- $t_new_value = constant_replace( trim( $t_split[1], " \t\n\r\0\x0B\"'" ) );
- $t_value[ $t_new_key ] = $t_new_value;
- } else {
- // regular array
- $t_value[ $key ] = constant_replace( trim( $value, " \t\n\r\0\x0B\"'" ) );
- }
- }
- } else {
- // scalar value
- $t_value = constant_replace( trim( $t_full_string ) );
- }
+ switch( $t_type ) {
+ case CONFIG_TYPE_STRING:
+ $t_value = $f_value;
+ break;
+ case CONFIG_TYPE_INT:
+ $t_value = (integer) constant_replace( trim( $f_value ) );
+ break;
+ case CONFIG_TYPE_FLOAT:
+ $t_value = (float) constant_replace( trim( $f_value ) );
+ break;
+ case CONFIG_TYPE_COMPLEX:
+ default:
+ $t_value = process_complex_value( $f_value );
+ break;
}
config_set( $f_config_option, $t_value, $f_user_id, $f_project_id );
@@ -116,13 +102,139 @@
/**
- * Check if the passed string is a constant and return its value
+ * Helper function to recursively process complex types
+ * We support the following kind of variables here:
+ * 1. constant values (like the ON/OFF switches): they are defined as constants mapping to numeric values
+ * 2. simple arrays with the form: array( a, b, c, d )
+ * 3. associative arrays with the form: array( a=>1, b=>2, c=>3, d=>4 )
+ * 4. multi-dimensional arrays
+ * commas and '=>' within strings are handled
+ *
+ * @param string $p_value Complex value to process
+ * @return parsed variable
+ */
+ function process_complex_value( $p_value, $p_trimquotes = false ) {
+ static $s_regex_array = null;
+ static $s_regex_string = null;
+ static $s_regex_element = null;
+
+ $t_value = trim( $p_value );
+
+ # Parsing regex initialization
+ if( is_null( $s_regex_array ) ) {
+ $s_regex_array = '^array[\s]*\((.*)\)$';
+ $s_regex_string =
+ # unquoted string (word)
+ '[\w]+' . '|' .
+ # single-quoted string
+ "'(?:[^'\\\\]|\\\\.)*'" . '|' .
+ # double-quoted string
+ '"(?:[^"\\\\]|\\\\.)*"';
+ # The following complex regex will parse individual array elements,
+ # taking into consideration sub-arrays, associative arrays and single,
+ # double and un-quoted strings
+ # @TODO dregad reverse pattern logic for sub-array to avoid match on array(xxx)=>array(xxx)
+ $s_regex_element = '('
+ # Main sub-pattern - match one of
+ . '(' .
+ # sub-array: ungreedy, no-case match ignoring nested parenthesis
+ '(?:(?iU:array\s*(?:\\((?:(?>[^()]+)|(?1))*\\))))' . '|' .
+ $s_regex_string
+ . ')'
+ # Optional pattern for associative array, back-referencing the
+ # above main pattern
+ . '(?:\s*=>\s*(?2))?' .
+ ')';
+ }
+
+ if( preg_match( "/$s_regex_array/s", $t_value, $t_match ) === 1 ) {
+ # It's an array - process each element
+ $t_processed = array();
+
+ if( preg_match_all( "/$s_regex_element/", $t_match[1], $t_elements ) ) {
+ foreach( $t_elements[0] as $key => $element ) {
+ if( !trim( $element ) ) {
+ # Empty element - skip it
+ continue;
+ }
+ # Check if element is associative array
+ preg_match_all( "/($s_regex_string)\s*=>\s*(.*)/", $element, $t_split );
+ if( !empty( $t_split[0] ) ) {
+ # associative array
+ $t_new_key = constant_replace( trim( $t_split[1][0], " \t\n\r\0\x0B\"'" ) );
+ $t_new_value = process_complex_value( $t_split[2][0], true );
+ $t_processed[$t_new_key] = $t_new_value;
+ } else {
+ # regular array
+ $t_new_value = process_complex_value( $element );
+ $t_processed[$key] = $t_new_value;
+ }
+ }
+ }
+ return $t_processed;
+ } else {
+ # Scalar value
+ if( $p_trimquotes ) {
+ $t_value = trim( $t_value, " \t\n\r\0\x0B\"'" );
+ }
+ return constant_replace( $t_value );
+ }
+ }
+
+ /**
+ * Split by commas, but ignore commas that are within quotes or parenthesis.
+ * Ignoring commas within parenthesis helps allow for multi-dimensional arrays.
+ * @param $p_string string to split
+ * @return array
+ */
+ function special_split ( $p_string ) {
+ $t_values = array();
+ $t_array_element = "";
+ $t_paren_level = 0;
+ $t_inside_quote = False;
+ $t_escape_next = False;
+
+ foreach( str_split( trim( $p_string ) ) as $character ) {
+ if( $t_escape_next ) {
+ $t_array_element .= $character;
+ $t_escape_next = False;
+ } else if( $character == "," && $t_paren_level==0 && !$t_inside_quote ) {
+ array_push( $t_values, $t_array_element );
+ $t_array_element = "";
+ } else {
+ if( $character == "(" && !$t_inside_quote ) {
+ $t_paren_level ++;
+ } else if( $character == ")" && !$t_inside_quote ) {
+ $t_paren_level --;
+ } else if( $character == "'" ) {
+ $t_inside_quote = !$t_inside_quote;
+ } else if( $character == "\\" ) {
+ # escape character
+ $t_escape_next = true;
+ # keep the escape if the string will be going through another recursion
+ if( $t_paren_level > 0 ) {
+ $t_array_element .= $character;
+ }
+ continue;
+ }
+ $t_array_element .= $character;
+ }
+ }
+ array_push( $t_values, $t_array_element );
+ return $t_values;
+ }
+
+
+ /**
+ * Check if the passed string is a constant and returns its value
+ * if yes, or the string itself if not
+ * @param $p_name string to check
+ * @return mixed|string value of constant $p_name, or $p_name itself
*/
function constant_replace( $p_name ) {
- $t_result = $p_name;
- if ( is_string( $p_name ) && defined( $p_name ) ) {
- // we have a constant
- $t_result = constant( $p_name );
+ if( is_string( $p_name ) && defined( $p_name ) ) {
+ # we have a constant
+ return constant( $p_name );
}
- return $t_result;
+ return $p_name;
}
View
39 config_defaults_inc.php
@@ -2803,28 +2803,36 @@
*****************************/
/**
- * --- cookie path ---------------
- * set this to something more restrictive if needed
- * http://www.php.net/manual/en/function.setcookie.php
+ * Specifies the path under which a cookie is visible
+ * All scripts in this directory and its sub-directories will be able
+ * to access MantisBT cookies.
+ * It is recommended to set this to the actual MantisBT path.
+ * @link http://php.net/function.setcookie
* @global string $g_cookie_path
*/
$g_cookie_path = '/';
/**
- *
+ * The domain that the MantisBT cookies are available to
* @global string $g_cookie_domain
*/
$g_cookie_domain = '';
/**
- * cookie version for view_all_page
+ * Version of the view_all_page cookie
+ * It is not expected for the user to need to change this setting
+ * @see $g_view_all_cookie
* @global string $g_cookie_version
*/
$g_cookie_version = 'v8';
/**
- * --- cookie prefix ---------------
- * set this to a unique identifier. No spaces or periods.
+ * Prefix for all MantisBT cookies
+ * This should be an identifier which does not include spaces or periods,
+ * and should be unique per MantisBT installation, especially if
+ * $g_cookie_path is not restricting the cookies' scope to the actual
+ * MantisBT directory.
+ * @see $g_cookie_path
* @global string $g_cookie_prefix
*/
$g_cookie_prefix = 'MANTIS';
@@ -2848,10 +2856,16 @@
$g_view_all_cookie = '%cookie_prefix%_VIEW_ALL_COOKIE';
/**
- *
- * @global string $g_manage_cookie
+ * Stores the filter criteria for the Manage User page
+ * @global string $g_manage_users_cookie
+ */
+ $g_manage_users_cookie = '%cookie_prefix%_MANAGE_USERS_COOKIE';
+
+ /**
+ * Stores the filter criteria for the Manage Config Report page
+ * @global string $g_manage_config_cookie
*/
- $g_manage_cookie = '%cookie_prefix%_MANAGE_COOKIE';
+ $g_manage_config_cookie = '%cookie_prefix%_MANAGE_CONFIG_COOKIE';
/**
*
@@ -3915,8 +3929,9 @@
'absolute_path_default_upload_folder', 'ldap_simulation_file_path', 'cookie_path',
'plugin_path', 'db_table_prefix', 'db_table_suffix', 'db_table', 'allow_permanent_cookie',
'cookie_time_length', 'cookie_domain', 'cookie_version', 'cookie_prefix',
- 'string_cookie', 'project_cookie', 'view_all_cookie', 'manage_cookie', 'logout_cookie',
- 'bug_list_cookie', 'db_username', 'db_password', 'db_schema', 'db_type', 'hostname',
+ 'string_cookie', 'project_cookie', 'view_all_cookie', 'manage_users_cookie',
+ 'manage_config_cookie', 'logout_cookie', 'bug_list_cookie',
+ 'db_username', 'db_password', 'db_schema', 'db_type', 'hostname',
'allow_signup', 'database_name', 'show_queries_count', 'show_queries_threshold',
'show_queries_list', 'admin_checks', 'version_suffix', 'global_settings', 'use_iis',
'default_language', 'language_choices_arr', 'language_auto_map', 'fallback_language',
View
1  core/constant_inc.php
@@ -469,6 +469,7 @@
define( 'TOKEN_EXPIRY_COLLAPSE', 365 * 24 * 60 * 60 );
# config types
+define( 'CONFIG_TYPE_DEFAULT', 0 );
define( 'CONFIG_TYPE_INT', 1 );
define( 'CONFIG_TYPE_STRING', 2 );
define( 'CONFIG_TYPE_COMPLEX', 3 );
View
16 core/form_api.php
@@ -77,20 +77,26 @@ function form_security_token( $p_form_name ) {
/**
* Get a hidden form element containing a generated form security token.
- * @param string Form name
+ * @param string $p_form_name Form name
+ * @param string $p_security_token Optional security token, previously generated for the same form
* @return string Hidden form element to output
*/
-function form_security_field( $p_form_name ) {
+function form_security_field( $p_form_name, $p_security_token = null ) {
if ( PHP_CLI == php_mode() || OFF == config_get_global( 'form_security_validation' ) ) {
return '';
}
- $t_string = form_security_token( $p_form_name );
+ if( is_null( $p_security_token ) ) {
+ $p_security_token = form_security_token( $p_form_name );
+ }
# Create the form element HTML string for the security token
$t_form_token = $p_form_name . '_token';
- $t_element = '<input type="hidden" name="%s" value="%s"/>';
- $t_element = sprintf( $t_element, $t_form_token, $t_string );
+ $t_element = sprintf(
+ '<input type="hidden" name="%s" value="%s"/>',
+ $t_form_token,
+ $p_security_token
+ );
return $t_element;
}
View
3  core/helper_api.php
@@ -281,7 +281,8 @@ function helper_set_current_project( $p_project_id ) {
*/
function helper_clear_pref_cookies() {
gpc_clear_cookie( config_get( 'project_cookie' ) );
- gpc_clear_cookie( config_get( 'manage_cookie' ) );
+ gpc_clear_cookie( config_get( 'manage_users_cookie' ) );
+ gpc_clear_cookie( config_get( 'manage_config_cookie' ) );
}
/**
View
3  core/obsolete.php
@@ -142,3 +142,6 @@
# changes in 1.2.8
config_obsolete( 'show_attachment_indicator' );
config_obsolete( 'default_avatar', '' );
+
+# changes in 1.2.13
+config_obsolete( 'manage_cookie', 'manage_users_cookie' );
View
28 core/print_api.php
@@ -1296,22 +1296,36 @@ function print_manage_project_sort_link( $p_page, $p_string, $p_field, $p_dir, $
print_link( "$p_page?sort=$t_field&dir=$t_dir", $p_string );
}
-# print a button which presents a standalone form.
-# $p_action_page - The action page
-# $p_label - The button label
-# $p_args_to_post - An associative array with key => value to be posted, can be null.
-function print_button( $p_action_page, $p_label, $p_args_to_post = null ) {
+/**
+ * Print a button which presents a standalone form.
+ * If $p_security_token is OFF, the button's form will not contain a security
+ * field; this is useful when form does not result in modifications (CSRF is not
+ * needed). If otherwise specified (i.e. not null), the parameter must contain
+ * a valid security token, previously generated by form_security_token().
+ * Use this to avoid performance issues when loading pages having many calls to
+ * this function, such as adm_config_report.php.
+ * @param string $p_action_page The action page
+ * @param string $p_label The button label
+ * @param array $p_args_to_post Associative array of arguments to be posted, with
+ * arg name => value, defaults to null (no args)
+ * @param mixed $p_security_token Optional; null (default), OFF or security token string
+ * @see form_security_token()
+ */
+function print_button( $p_action_page, $p_label, $p_args_to_post = null, $p_security_token = null ) {
$t_form_name = explode( '.php', $p_action_page, 2 );
# TODO: ensure all uses of print_button supply arguments via $p_args_to_post (POST)
# instead of via $p_action_page (GET). Then only add the CSRF form token if
# arguments are being sent via the POST method.
echo '<form method="post" action="', htmlspecialchars( $p_action_page ), '">';
- echo form_security_field( $t_form_name[0] );
+ if( $p_security_token !== OFF ) {
+ echo form_security_field( $t_form_name[0], $p_security_token );
+ }
echo '<input type="submit" class="button-small" value="', $p_label, '" />';
if( $p_args_to_post !== null ) {
foreach( $p_args_to_post as $t_var => $t_value ) {
- echo "<input type=\"hidden\" name=\"$t_var\" value=\"$t_value\" />";
+ echo '<input type="hidden" name="' . $t_var .
+ '" value="' . htmlentities( $t_value ) . '" />';
}
}
View
86 docbook/administration_guide/en/configuration.sgml
@@ -2515,51 +2515,87 @@
<section id="admin.config.cookies">
<title>Cookies</title>
- <para>The configuration variables $g_string_cookie,
- $g_project_cookie, $g_view_all_cookie, $g_manage_cookie are
- calculated based on $g_cookie_prefix. When you change the cookie
- prefix in config_inc.php, you need to follow it with a copy of the
- four lines that calculate the names for these cookies.
- </para>
<variablelist>
<varlistentry>
<term>$g_cookie_path</term>
<listitem>
- <para>This is specifies to the path under which a cookie is
- visible. All scripts in this directory and its sub-directories will
- be able to access MantisBT cookies. Default value is '/'. It is
- recommended to set this to the actual MantisBT path.
- </para>
+ <para>Specifies the path under which a cookie is visible.
+ </para>
+ <para>All scripts in this directory and its sub-directories
+ will be able to access MantisBT cookies.
+ </para>
+ <para>Default value is '/'.
+ It is recommended to set this to the actual MantisBT path.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term>$g_cookie_domain</term>
<listitem>
- <para>Unused</para>
+ <para>The domain that the MantisBT cookies are available to.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>$g_cookie_version</term>
<listitem>
- <para>Cookie version is used as a prefix for cookies that should
- be expire when the code is changed in a certain way. The developers
- would increase this version when necessary, which in effect will
- cause the creation of new cookies that are compatible with the new
- code. It is not expected for the user to need to change this
- setting.
- </para>
+ <para>Version of the view_all_page cookie.</para>
+ <para>This is used as a prefix for cookies that should
+ be expired when the code is changed in a certain way.
+ The developers would increase this version when necessary,
+ which in effect will cause the creation of new cookies
+ that are compatible with the new code.
+ </para>
+ <para>It is not expected for the user to need to change this
+ setting.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term>$g_cookie_prefix</term>
<listitem>
- <para>This should be set to a unique identifier which does not
- include spaces or periods. Again, this should be unique per
- MantisBT installation, especially if $g_cookie_path is not
- restricting the cookies scope to the actual MantisBT
- directory.
- </para>
+ <para>Prefix for all MantisBT cookies</para>
+ <para>This should be an identifier which does not include
+ spaces or periods, and should be unique per MantisBT
+ installation, especially if $g_cookie_path is not
+ restricting the cookies' scope to the actual
+ MantisBT directory.
+ </para>
+ <para>It applies to the cookies listed below. Their actual
+ names are calculated by prepending the prefix, and
+ it is not expected for the user to need to change these.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>$g_string_cookie</para>
+ </listitem>
+ <listitem>
+ <para>$g_project_cookie</para>
+ </listitem>
+ <listitem>
+ <para>$g_view_all_cookie</para>
+ </listitem>
+ <listitem>
+ <para>$g_manage_users_cookie</para>
+ <para>Stores the filter criteria for the
+ Manage Users page
+ </para>
+ </listitem>
+ <listitem>
+ <para>$g_manage_config_cookie</para>
+ <para>Stores the filter criteria for the
+ Manage Config Report page
+ </para>
+ </listitem>
+ <listitem>
+ <para>$g_logout_cookie</para>
+ </listitem>
+ <listitem>
+ <para>$g_bug_list_cookie</para>
+ </listitem>
+ </itemizedlist>
+
</listitem>
</varlistentry>
</variablelist>
View
3  lang/strings_english.txt
@@ -748,6 +748,7 @@ $s_create_user_button = 'Create User';
# manage_page.php
$s_hide_disabled = 'Hide Disabled';
$s_filter_button = 'Apply Filter';
+$s_default_filter = 'Default Filter';
$s_create_filter_link = 'Create Permalink'; # Permalink = Permanent Link
$s_create_short_link = 'Create Short Link';
$s_filter_permalink = 'Following is a permanent link to the currently configured filter:';
@@ -1433,7 +1434,7 @@ $s_delete_attachments = 'Delete attachments';
$s_delete_attachment_button = 'Delete';
$s_delete_attachment_sure_msg = 'Are you sure you wish to delete this attachment?';
$s_upload_issue_attachments = 'Upload issue attachments';
-$s_filters = 'filters';
+$s_filters = 'Filters';
$s_save_filters = 'Save filters';
$s_save_filters_as_shared = 'Save filters as shared';
$s_use_saved_filters = 'Use saved filters';
View
2  manage_user_page.php
@@ -40,7 +40,7 @@
$f_page_number = gpc_get_int( 'page_number', 1 );
$t_user_table = db_get_table( 'mantis_user_table' );
- $t_cookie_name = config_get( 'manage_cookie' );
+ $t_cookie_name = config_get( 'manage_users_cookie' );
$t_lock_image = '<img src="' . config_get( 'icon_path' ) . 'protected.gif" width="8" height="15" border="0" alt="' . lang_get( 'protected' ) . '" />';
$c_filter = '';
Please sign in to comment.
Something went wrong with that request. Please try again.