Skip to content

Commit e1c7879

Browse files
committed
Security: Sanitize language variable inputs and improve variable handling in multiple files
1 parent e343c76 commit e1c7879

File tree

8 files changed

+40
-54
lines changed

8 files changed

+40
-54
lines changed

main/admin/sub_language_ajax.inc.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@
1414
api_protect_admin_script();
1515

1616
$new_language = Security::remove_XSS($_REQUEST['new_language']);
17-
$language_variable = Security::remove_XSS($_REQUEST['variable_language']);
17+
$language_variable = ltrim(
18+
Security::remove_XSS($_REQUEST['variable_language']),
19+
'$'
20+
);
1821
$file_id = intval($_REQUEST['file_id']);
1922

20-
if (isset($new_language) && isset($language_variable) && isset($file_id)) {
23+
$variableIsValid = isset($language_variable) && preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $language_variable);
24+
25+
if (isset($new_language) && $variableIsValid && isset($file_id)) {
2126
$file_language = $language_files_to_load[$file_id].'.inc.php';
2227
$id_language = intval($_REQUEST['id']);
2328
$sub_language_id = intval($_REQUEST['sub']);
@@ -27,12 +32,7 @@
2732
$all_file_of_directory = SubLanguageManager::get_all_language_variable_in_file($path_folder);
2833
$return_value = SubLanguageManager::add_file_in_language_directory($path_folder);
2934

30-
//update variable language
31-
// Replace double quotes to avoid parse errors
32-
$new_language = str_replace('"', '\"', $new_language);
33-
// Replace new line signs to avoid parse errors - see #6773
34-
$new_language = str_replace("\n", "\\n", $new_language);
35-
$all_file_of_directory[$language_variable] = "\"".$new_language."\";";
35+
$all_file_of_directory[$language_variable] = $new_language;
3636
$result_array = [];
3737

3838
foreach ($all_file_of_directory as $key_value => $value_info) {

main/cron/lang/langstats.class.php

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,7 @@ public function get_variables_origin()
190190
$vars = [];
191191
$priority = ['trad4all'];
192192
foreach ($priority as $file) {
193-
$list = SubLanguageManager::get_all_language_variable_in_file(
194-
$path.$file.'.inc.php',
195-
true
196-
);
193+
$list = SubLanguageManager::get_all_language_variable_in_file($path.$file.'.inc.php');
197194
foreach ($list as $var => $trad) {
198195
$vars[$var] = $file.'.inc.php';
199196
}
@@ -203,10 +200,7 @@ public function get_variables_origin()
203200
if (substr($file, 0, 1) == '.' or in_array($file, $priority)) {
204201
continue;
205202
}
206-
$list = SubLanguageManager::get_all_language_variable_in_file(
207-
$path.$file,
208-
true
209-
);
203+
$list = SubLanguageManager::get_all_language_variable_in_file($path.$file);
210204
foreach ($list as $var => $trad) {
211205
$vars[$var] = $file;
212206
}

main/cron/lang/list_undefined_langvars.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
foreach ($list as $entry) {
2121
$file = $path.'/'.$entry;
2222
if (is_file($file)) {
23-
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file, true));
23+
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file));
2424
}
2525
}
2626
// get only the array keys (the language variables defined in language files)

main/cron/lang/list_unused_langvars.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
foreach ($list as $entry) {
2121
$file = $path.'/'.$entry;
2222
if (is_file($file)) {
23-
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file, true));
23+
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file));
2424
}
2525
}
2626
// get only the array keys (the language variables defined in language files)

main/cron/lang/switch_files_to_gettext.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
foreach ($list as $entry) {
2121
$file = $path.'/'.$entry;
2222
if (is_file($file)) {
23-
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file, true));
23+
$terms = array_merge($terms, SubLanguageManager::get_all_language_variable_in_file($file));
2424
}
2525
}
2626
foreach ($terms as $index => $translation) {

main/inc/ajax/lang.ajax.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
Security::clear_token();
2424
if (isset($_REQUEST['new_language']) && isset($_REQUEST['variable_language']) && isset($_REQUEST['category_id'])) {
2525
$newLanguage = Security::remove_XSS($_REQUEST['new_language']);
26-
$langVariable = Security::remove_XSS($_REQUEST['variable_language']);
26+
$langVariable = ltrim(
27+
Security::remove_XSS($_REQUEST['variable_language']),
28+
'$'
29+
);
2730
$categoryId = (int) $_REQUEST['category_id'];
2831
$languageId = (int) $_REQUEST['id'];
2932
$subLanguageId = (int) $_REQUEST['sub'];
@@ -41,10 +44,7 @@
4144
$returnValue = SubLanguageManager::add_file_in_language_directory($pathFolder);
4245

4346
//update variable language
44-
// Replace double quotes to avoid parse errors
45-
$newLanguage = str_replace('"', '\"', $newLanguage);
46-
$newLanguage = str_replace("\n", "\\n", $newLanguage);
47-
$allFileOfDirectory[$langVariable] = "\"".$newLanguage."\";";
47+
$allFileOfDirectory[$langVariable] = $newLanguage;
4848

4949
$resultArray = [];
5050
foreach ($allFileOfDirectory as $key => $value) {

main/inc/lib/sub_language.class.php

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -119,31 +119,23 @@ public static function get_all_information_of_language($parent_id)
119119
* Get all information of chamilo file.
120120
*
121121
* @param string $system_path_file The chamilo path file (/var/www/chamilo/main/lang/spanish/gradebook.inc.php)
122-
* @param bool $get_as_string_index Whether we want to remove the '$' prefix in the results or not
123122
*
124123
* @return array Contains all information of chamilo file
125124
*/
126-
public static function get_all_language_variable_in_file($system_path_file, $get_as_string_index = false)
127-
{
128-
$res_list = [];
129-
if (!is_readable($system_path_file)) {
130-
return $res_list;
131-
}
132-
$info_file = file($system_path_file);
133-
foreach ($info_file as $line) {
134-
if (substr($line, 0, 1) != '$') {
135-
continue;
136-
}
137-
list($var, $val) = explode('=', $line, 2);
138-
$var = trim($var);
139-
$val = trim($val);
140-
if ($get_as_string_index) { //remove the prefix $
141-
$var = substr($var, 1);
142-
}
143-
$res_list[$var] = $val;
144-
}
125+
public static function get_all_language_variable_in_file(string $system_path_file): array {
126+
ob_start();
127+
128+
include $system_path_file;
145129

146-
return $res_list;
130+
ob_end_clean();
131+
132+
$variables = get_defined_vars();
133+
134+
unset($variables['system_path_file']);
135+
unset($variables['get_as_string_index']);
136+
unset($variables['php_errormsg']);
137+
138+
return $variables;
147139
}
148140

149141
/**
@@ -171,16 +163,16 @@ public static function add_file_in_language_directory($system_path_file)
171163
*/
172164
public static function write_data_in_file($path_file, $new_term, $new_variable)
173165
{
166+
// Replace double quotes to avoid parse errors
167+
$new_term = addcslashes($new_term, "\$\"\\");
168+
// Replace new line signs to avoid parse errors - see #6773
169+
$new_term = str_replace("\n", "\\n", $new_term);
170+
174171
$return_value = false;
175-
$new_data = $new_variable.'='.$new_term;
172+
$new_data = '$'.$new_variable.'="'.$new_term.'";'.PHP_EOL;
176173
$resource = @fopen($path_file, "a");
177174
if (file_exists($path_file) && $resource) {
178-
if (fwrite($resource, $new_data.PHP_EOL) === false) {
179-
//not allow to write
180-
$return_value = false;
181-
} else {
182-
$return_value = true;
183-
}
175+
$return_value = !(fwrite($resource, $new_data) === false);
184176
fclose($resource);
185177
}
186178

tests/scripts/build_translation_request_file.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
$referenceTerms = array();
2020
$file = $path . $referenceLanguage . '/trad4all.inc.php';
2121
if (is_file($file)) {
22-
$referenceTerms = array_merge($referenceTerms, SubLanguageManager::get_all_language_variable_in_file($file,true));
22+
$referenceTerms = array_merge($referenceTerms, SubLanguageManager::get_all_language_variable_in_file($file));
2323
}
2424
// get only the array keys (the language variables defined in language files)
2525
$definedTerms = array_keys($referenceTerms);
@@ -32,7 +32,7 @@
3232
$l = strlen(api_get_path(SYS_PATH));
3333
$file = $path . $language . '/trad4all.inc.php';
3434
if (is_file($file)) {
35-
$nonMissingTerms = array_merge($nonMissingTerms, SubLanguageManager::get_all_language_variable_in_file($file,true));
35+
$nonMissingTerms = array_merge($nonMissingTerms, SubLanguageManager::get_all_language_variable_in_file($file));
3636
}
3737
$nonMissingTerms = array_keys($nonMissingTerms);
3838
//print_r($nonMissingTerms);

0 commit comments

Comments
 (0)