Merge remote-tracking branch 'upstream/preprodparkur' into ofaj

ofaj
NicoDucou 2 years ago
commit 7b6042e7b2
  1. 22
      .htaccess
  2. 6
      main/admin/configure_extensions.php
  3. 290
      main/inc/ajax/document.ajax.php
  4. 148
      main/inc/ajax/dropbox.ajax.php
  5. 188
      main/inc/ajax/exercise.ajax.php
  6. 42
      main/inc/ajax/work.ajax.php
  7. 24
      main/inc/lib/fileUpload.lib.php
  8. 232
      main/install/configuration.dist.php
  9. 10
      main/lp/openoffice_document.class.php
  10. 14
      main/lp/openoffice_presentation.class.php
  11. 5
      main/lp/openoffice_text.class.php
  12. 5
      main/lp/openoffice_text_document.class.php
  13. 11
      main/session/session_import.php
  14. 42
      main/webservices/additional_webservices.php

@ -91,3 +91,25 @@ AddType application/font-woff .woff .woff2
ExpiresActive On
ExpiresByType application/font-woff "access plus 1 month"
</IfModule>
# Force SSL/HTTPS
# We recommend you place this block in your VirtualHost config rather
# than uncommenting it below. However, if you have no other way,
# feel free to uncomment it, but please remember that this file will
# be overwritten during your next Chamilo update.
# Also note this will only work if you have an SSL certificate
# configured elsewhere in your Apache configuration.
#RewriteCond %{HTTPS} !=on
#RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
#<IfModule mod_headers.c>
# Header always set Content-Security-Policy "upgrade-insecure-requests;"
#</IfModule>
# Disallow direct access to /main/inc/lib/javascript/bigupload/files
RedirectMatch 403 ^/main/inc/lib/javascript/bigupload/files
# Disallow MIME sniffing to prevent XSS from unknown/incorrect file extensions
<IfModule mod_headers.c>
Header always set X-Content-Type-Options nosniff
</IfModule>

@ -158,7 +158,11 @@ Display::display_header($nameTool);
<form method="POST" class="form-horizontal" action="<?php echo api_get_self(); ?>">
<?php
$form = new FormValidator('ppt2lp');
$form->addElement('text', 'host', get_lang('Host'));
if (api_get_configuration_value('webservice_remote_ppt2png_enable') == true) {
$form->addElement('text', 'host', get_lang('Host'));
} else {
$form->addElement('text', 'host', [get_lang('Host'),'Remote host disabled - set webservice_remote_ppt2png_enable setting to true in configuration.php to enable']);
}
//$form -> addElement('html','<br /><br />');
$form->addElement('text', 'port', get_lang('Port'));
//$form -> addElement('html','<br /><br />');

@ -27,117 +27,231 @@ switch ($action) {
break;
case 'upload_file':
api_protect_course_script(true);
// User access same as upload.php
$is_allowed_to_edit = api_is_allowed_to_edit(null, true);
$sessionId = api_get_session_id();
if (isset($_REQUEST['chunkAction']) && 'send' === $_REQUEST['chunkAction']) {
// It uploads the files in chunks
if (!empty($_FILES)) {
$tempDirectory = api_get_path(SYS_ARCHIVE_PATH);
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
}
}
if (!empty($fileList)) {
foreach ($fileList as $n => $file) {
$tmpFile = disable_dangerous_file(
api_replace_dangerous_char($file['name'])
);
file_put_contents(
$tempDirectory.$tmpFile,
fopen($file['tmp_name'], 'r'),
FILE_APPEND
);
}
}
}
echo json_encode([
'files' => $_FILES,
'errorStatus' => 0,
]);
exit;
} else {
// User access same as upload.php
$is_allowed_to_edit = api_is_allowed_to_edit(null, true);
if (!$is_allowed_to_edit && $sessionId && $_REQUEST['curdirpath'] == "/basic-course-documents__{$sessionId}__0") {
$session = SessionManager::fetch($sessionId);
$sessionId = api_get_session_id();
if (!empty($session) && $session['session_admin_id'] == api_get_user_id()) {
$is_allowed_to_edit = true;
if (!$is_allowed_to_edit && $sessionId && $_REQUEST['curdirpath'] == "/basic-course-documents__{$sessionId}__0") {
$session = SessionManager::fetch($sessionId);
if (!empty($session) && $session['session_admin_id'] == api_get_user_id()) {
$is_allowed_to_edit = true;
}
}
}
// This needs cleaning!
if (api_get_group_id()) {
$groupInfo = GroupManager::get_group_properties(api_get_group_id());
// Only course admin or group members allowed
if ($is_allowed_to_edit || GroupManager::is_user_in_group(api_get_user_id(), $groupInfo)) {
if (!GroupManager::allowUploadEditDocument(api_get_user_id(), api_get_course_int_id(), $groupInfo)) {
// This needs cleaning!
if (api_get_group_id()) {
$groupInfo = GroupManager::get_group_properties(api_get_group_id());
// Only course admin or group members allowed
if ($is_allowed_to_edit || GroupManager::is_user_in_group(api_get_user_id(), $groupInfo)) {
if (!GroupManager::allowUploadEditDocument(
api_get_user_id(),
api_get_course_int_id(),
$groupInfo
)) {
exit;
}
} else {
exit;
}
} elseif ($is_allowed_to_edit ||
DocumentManager::is_my_shared_folder(api_get_user_id(), $_REQUEST['curdirpath'], api_get_session_id())
) {
// ??
} else {
// No course admin and no group member...
exit;
}
} elseif ($is_allowed_to_edit ||
DocumentManager::is_my_shared_folder(api_get_user_id(), $_REQUEST['curdirpath'], api_get_session_id())
) {
// ??
} else {
// No course admin and no group member...
exit;
}
$directoryParentId = isset($_POST['directory_parent_id']) ? $_POST['directory_parent_id'] : 0;
$currentDirectory = '';
if (empty($directoryParentId)) {
$currentDirectory = isset($_REQUEST['curdirpath']) ? $_REQUEST['curdirpath'] : '';
} else {
$documentData = DocumentManager::get_document_data_by_id($directoryParentId, api_get_course_id());
if ($documentData) {
$currentDirectory = $documentData['path'];
$directoryParentId = isset($_POST['directory_parent_id']) ? (int) $_POST['directory_parent_id'] : 0;
$currentDirectory = '';
if (empty($directoryParentId)) {
$currentDirectory = $_REQUEST['curdirpath'] ?? '';
} else {
$documentData = DocumentManager::get_document_data_by_id($directoryParentId, api_get_course_id());
if ($documentData) {
$currentDirectory = $documentData['path'];
}
}
}
$ifExists = isset($_POST['if_exists']) ? $_POST['if_exists'] : '';
$unzip = isset($_POST['unzip']) ? 1 : 0;
if (empty($ifExists)) {
$fileExistsOption = api_get_setting('document_if_file_exists_option');
$defaultFileExistsOption = 'rename';
if (!empty($fileExistsOption)) {
$defaultFileExistsOption = $fileExistsOption;
if (empty($currentDirectory)) {
$currentDirectory = DIRECTORY_SEPARATOR;
}
} else {
$defaultFileExistsOption = $ifExists;
}
$ifExists = $_POST['if_exists'] ?? '';
$unzip = isset($_POST['unzip']) ? 1 : 0;
if (!empty($_FILES)) {
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
if (empty($ifExists)) {
$fileExistsOption = api_get_setting('document_if_file_exists_option');
$defaultFileExistsOption = 'rename';
if (!empty($fileExistsOption)) {
$defaultFileExistsOption = $fileExistsOption;
}
} else {
$defaultFileExistsOption = $ifExists;
}
$resultList = [];
foreach ($fileList as $file) {
$globalFile = [];
$globalFile['files'] = $file;
$result = DocumentManager::upload_document(
$globalFile,
$currentDirectory,
'',
'', // comment
$unzip,
$defaultFileExistsOption,
false,
false,
'files'
);
$json = [];
if (!empty($result) && is_array($result)) {
$json['name'] = api_htmlentities($result['title']);
$json['link'] = Display::url(
api_htmlentities($result['title']),
api_htmlentities($result['url']),
['target' => '_blank']
);
$json['url'] = $result['url'];
$json['size'] = format_file_size($file['size']);
$json['type'] = api_htmlentities($file['type']);
$json['result'] = Display::return_icon(
'accept.png',
get_lang('Uploaded')
if (!empty($_FILES)) {
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
}
}
$resultList = [];
foreach ($fileList as $file) {
if (isset($_REQUEST['chunkAction']) && 'done' === $_REQUEST['chunkAction']) {
// to rename and move the finished file
$tmpFile = disable_dangerous_file(
api_replace_dangerous_char($file['name'])
);
$chunkedFile = api_get_path(SYS_ARCHIVE_PATH).$tmpFile;
$file['tmp_name'] = $chunkedFile;
$file['size'] = filesize($chunkedFile);
$file['copy_file'] = true;
}
$globalFile = [];
$globalFile['files'] = $file;
$result = DocumentManager::upload_document(
$globalFile,
$currentDirectory,
'',
'', // comment
$unzip,
$defaultFileExistsOption,
false,
false,
'files'
);
} else {
$json['name'] = isset($file['name']) ? $file['name'] : get_lang('Unknown');
$json['url'] = '';
$json['error'] = get_lang('Error');
$json = [];
if (!empty($result) && is_array($result)) {
$json['name'] = api_htmlentities($result['title']);
$json['link'] = Display::url(
api_htmlentities($result['title']),
api_htmlentities($result['url']),
['target' => '_blank']
);
$json['url'] = $result['url'];
$json['size'] = format_file_size($file['size']);
$json['type'] = api_htmlentities($file['type']);
$json['result'] = Display::return_icon(
'accept.png',
get_lang('Uploaded')
);
} else {
$json['name'] = $file['name'] ?? get_lang('Unknown');
$json['url'] = '';
$json['error'] = get_lang('Error');
}
$resultList[] = $json;
}
$resultList[] = $json;
echo json_encode(['files' => $resultList]);
exit;
}
}
break;
case 'ck_uploadimage':
api_protect_course_script(true);
// it comes from uploaimage drag and drop ckeditor
$isCkUploadImage = ($_COOKIE['ckCsrfToken'] == $_POST['ckCsrfToken']);
echo json_encode(['files' => $resultList]);
if (!$isCkUploadImage) {
exit;
}
$data = [];
$fileUpload = $_FILES['upload'];
$currentDirectory = Security::remove_XSS($_REQUEST['curdirpath']);
$isAllowedToEdit = api_is_allowed_to_edit(null, true);
if ($isAllowedToEdit) {
$globalFile = ['files' => $fileUpload];
$result = DocumentManager::upload_document(
$globalFile,
$currentDirectory,
'',
'',
0,
'rename',
false,
false,
'files'
);
if ($result) {
$relativeUrl = str_replace(api_get_path(WEB_PATH), '/', $result['direct_url']);
$data = [
'uploaded' => 1,
'fileName' => $fileUpload['name'],
'url' => $relativeUrl,
];
}
} else {
$userId = api_get_user_id();
$syspath = UserManager::getUserPathById($userId, 'system').'my_files'.$currentDirectory;
if (!is_dir($syspath)) {
mkdir($syspath, api_get_permissions_for_new_directories(), true);
}
$webpath = UserManager::getUserPathById($userId, 'web').'my_files'.$currentDirectory;
$fileUploadName = $fileUpload['name'];
if (file_exists($syspath.$fileUploadName)) {
$extension = pathinfo($fileUploadName, PATHINFO_EXTENSION);
$fileName = pathinfo($fileUploadName, PATHINFO_FILENAME);
$suffix = '_'.uniqid();
$fileUploadName = $fileName.$suffix.'.'.$extension;
}
if (move_uploaded_file($fileUpload['tmp_name'], $syspath.$fileUploadName)) {
$url = $webpath.$fileUploadName;
$relativeUrl = str_replace(api_get_path(WEB_PATH), '/', $url);
$data = [
'uploaded' => 1,
'fileName' => $fileUploadName,
'url' => $relativeUrl,
];
}
}
echo json_encode($data);
exit;
break;
case 'document_preview':
$courseInfo = api_get_course_info_by_id($_REQUEST['course_id']);
if (!empty($courseInfo) && is_array($courseInfo)) {

@ -11,72 +11,116 @@ $action = $_REQUEST['a'];
switch ($action) {
case 'upload_file':
api_protect_course_script(true);
// User access same as upload.php
$is_allowed_to_edit = api_is_allowed_to_edit(null, true);
$recipients = isset($_POST['recipients']) ? $_POST['recipients'] : '';
$id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
if (isset($_REQUEST['chunkAction']) && 'send' === $_REQUEST['chunkAction']) {
// It uploads the files in chunks
if (!empty($_FILES)) {
$tempDirectory = api_get_path(SYS_ARCHIVE_PATH);
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
}
}
if (!empty($fileList)) {
foreach ($fileList as $n => $file) {
$tmpFile = disable_dangerous_file(
api_replace_dangerous_char($file['name'])
);
if (empty($recipients) && empty($id)) {
$resultList[] = ['error' => get_lang('YouMustSelectAtLeastOneDestinee')];
echo json_encode(['files' => $resultList]);
file_put_contents(
$tempDirectory.$tmpFile,
fopen($file['tmp_name'], 'r'),
FILE_APPEND
);
}
}
}
echo json_encode([
'files' => $_FILES,
'errorStatus' => 0,
]);
exit;
}
$work = null;
if (!empty($id)) {
$work = new Dropbox_SentWork($id);
if (empty($work)) {
$resultList[] = ['error' => get_lang('Error')];
} else {
// User access same as upload.php
$is_allowed_to_edit = api_is_allowed_to_edit(null, true);
$recipients = isset($_POST['recipients']) ? $_POST['recipients'] : '';
$id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
if (empty($recipients) && empty($id)) {
$resultList[] = ['error' => get_lang('YouMustSelectAtLeastOneDestinee')];
echo json_encode(['files' => $resultList]);
exit;
}
}
if (!empty($_FILES)) {
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
$work = null;
if (!empty($id)) {
$work = new Dropbox_SentWork($id);
if (empty($work)) {
$resultList[] = ['error' => get_lang('Error')];
echo json_encode(['files' => $resultList]);
exit;
}
}
$resultList = [];
foreach ($fileList as $file) {
$globalFile = [];
$globalFile['files'] = $file;
/** @var Dropbox_SentWork $result */
$result = store_add_dropbox($file, $work);
if (!empty($_FILES)) {
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
}
}
$resultList = [];
foreach ($fileList as $file) {
if (isset($_REQUEST['chunkAction']) && 'done' === $_REQUEST['chunkAction']) {
// to rename and move the finished file
$chunkedFile = api_get_path(SYS_ARCHIVE_PATH).$file['name'];
$file['tmp_name'] = $chunkedFile;
$file['size'] = filesize($chunkedFile);
$file['copy_file'] = true;
}
$globalFile = [];
$globalFile['files'] = $file;
/** @var Dropbox_SentWork $result */
$result = store_add_dropbox($file, $work);
$json = [];
if (!empty($result)) {
$json['name'] = Display::url(
api_htmlentities($result->title),
api_htmlentities(api_get_path(WEB_CODE_PATH).'dropbox/index.php?'.api_get_cidreq()),
['target' => '_blank']
);
$json = [];
if (!empty($result)) {
$json['name'] = Display::url(
api_htmlentities($result->title),
api_htmlentities(api_get_path(WEB_CODE_PATH).'dropbox/index.php?'.api_get_cidreq()),
['target' => '_blank']
);
$json['url'] = api_get_path(WEB_CODE_PATH).'dropbox/index.php?'.api_get_cidreq();
$json['size'] = format_file_size($result->filesize);
$json['type'] = api_htmlentities($file['type']);
$json['result'] = Display::return_icon(
'accept.png',
get_lang('Uploaded')
);
} else {
$json['result'] = Display::return_icon(
'exclamation.png',
get_lang('Error')
);
$json['url'] = api_get_path(WEB_CODE_PATH).'dropbox/index.php?'.api_get_cidreq();
$json['size'] = format_file_size($result->filesize);
$json['type'] = api_htmlentities($file['type']);
$json['result'] = Display::return_icon(
'accept.png',
get_lang('Uploaded')
);
} else {
$json['result'] = Display::return_icon(
'exclamation.png',
get_lang('Error')
);
}
$resultList[] = $json;
}
$resultList[] = $json;
}
echo json_encode(['files' => $resultList]);
echo json_encode(['files' => $resultList]);
exit;
}
}
exit;
break;
}
exit;

@ -811,6 +811,194 @@ switch ($action) {
header('Content-Type: application/json');
echo json_encode($result);
break;
case 'browser_test':
$quizCheckButtonEnabled = api_get_configuration_value('quiz_check_button_enable');
if ($quizCheckButtonEnabled) {
if (isset($_POST['sleep'])) {
sleep(2);
}
echo 'ok';
}
break;
case 'quiz_confirm_saved_answers':
if (false === api_get_configuration_value('quiz_confirm_saved_answers')) {
break;
}
$trackConfirmationId = isset($_POST['tc_id']) ? (int) $_POST['tc_id'] : 0;
$cId = api_get_course_int_id();
$sessionId = api_get_session_id();
$userId = api_get_user_id();
$confirmed = !empty($_POST['quiz_confirm_saved_answers_check']);
$em = Database::getManager();
$repo = $em->getRepository('ChamiloCoreBundle:TrackEExerciseConfirmation');
try {
if (!$trackConfirmationId) {
throw new Exception(get_lang('ErrorOccurred'));
}
/** @var TrackEExerciseConfirmation $trackConfirmation */
$trackConfirmation = $repo->findOneBy(
[
'id' => $trackConfirmationId,
'userId' => $userId,
'courseId' => $cId,
'sessionId' => $sessionId,
],
['createdAt' => 'DESC']
);
if (!$trackConfirmation) {
throw new Exception(get_lang('NotFound'));
}
$trackConfirmation
->setConfirmed($confirmed)
->setUpdatedAt(api_get_utc_datetime(null, false, true));
$em->persist($trackConfirmation);
$em->flush();
http_response_code(200);
} catch (Exception $exception) {
http_response_code(500);
echo Display::return_message($exception->getMessage(), 'error');
}
break;
case 'sign_attempt':
api_block_anonymous_users();
if ('true' !== api_get_plugin_setting('exercise_signature', 'tool_enable')) {
exit;
}
$file = isset($_REQUEST['file']) ? $_REQUEST['file'] : '';
if (empty($exeId) || empty($file)) {
echo 0;
exit;
}
$file = str_replace(' ', '+', $file);
$track = ExerciseLib::get_exercise_track_exercise_info($exeId);
if ($track) {
$result = ExerciseSignaturePlugin::saveSignature($currentUserId, $track, $file);
if ($result) {
echo 1;
exit;
}
}
echo 0;
break;
case 'upload_answer':
api_block_anonymous_users();
if (isset($_REQUEST['chunkAction']) && 'send' === $_REQUEST['chunkAction']) {
// It uploads the files in chunks
if (!empty($_FILES)) {
$tempDirectory = api_get_path(SYS_ARCHIVE_PATH);
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
}
}
if (!empty($fileList)) {
foreach ($fileList as $n => $file) {
$tmpFile = disable_dangerous_file(
api_replace_dangerous_char($file['name'])
);
file_put_contents(
$tempDirectory.$tmpFile,
fopen($file['tmp_name'], 'r'),
FILE_APPEND
);
}
}
}
echo json_encode([
'files' => $_FILES,
'errorStatus' => 0,
]);
exit;
} else {
if (!empty($_FILES)) {
$currentDirectory = Security::remove_XSS($_REQUEST['curdirpath']);
$userId = api_get_user_id();
// Upload answer path is created inside user personal folder my_files/upload_answer/[exe_id]/[question_id]
$syspath = UserManager::getUserPathById($userId, 'system').'my_files'.$currentDirectory;
@mkdir($syspath, api_get_permissions_for_new_directories(), true);
$webpath = UserManager::getUserPathById($userId, 'web').'my_files'.$currentDirectory;
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
}
}
$resultList = [];
foreach ($fileList as $file) {
$json = [];
if (isset($_REQUEST['chunkAction']) && 'done' === $_REQUEST['chunkAction']) {
// to rename and move the finished file
$chunkedFile = api_get_path(SYS_ARCHIVE_PATH).$file['name'];
$file['tmp_name'] = $chunkedFile;
$file['size'] = filesize($chunkedFile);
$file['copy_file'] = true;
}
$filename = api_replace_dangerous_char($file['name']);
$filename = disable_dangerous_file($filename);
if (isset($file['copy_file']) && $file['copy_file']) {
$uploaded = copy($file['tmp_name'], $syspath.$filename);
@unlink($file['tmp_name']);
} else {
$uploaded = move_uploaded_file($file['tmp_name'], $syspath.$filename);
}
if ($uploaded) {
$title = $filename;
$url = $webpath.$filename;
$json['name'] = api_htmlentities($title);
$json['link'] = Display::url(
api_htmlentities($title),
api_htmlentities($url),
['target' => '_blank']
);
$json['url'] = $url;
$json['size'] = format_file_size($file['size']);
$json['type'] = api_htmlentities($file['type']);
$json['result'] = Display::return_icon(
'accept.png',
get_lang('Uploaded')
);
} else {
$json['name'] = isset($file['name']) ? $filename : get_lang('Unknown');
$json['url'] = '';
$json['error'] = get_lang('Error');
}
$resultList[] = $json;
}
echo json_encode(['files' => $resultList]);
exit;
}
}
break;
default:
echo '';
}

@ -60,10 +60,44 @@ switch ($action) {
api_protect_course_script(true);
$workId = isset($_REQUEST['id']) ? $_REQUEST['id'] : '';
$workInfo = get_work_data_by_id($workId);
$sessionId = api_get_session_id();
$userId = api_get_user_id();
$groupId = api_get_group_id();
if (isset($_REQUEST['chunkAction']) && 'send' === $_REQUEST['chunkAction']) {
// It uploads the files in chunks
if (!empty($_FILES)) {
$tempDirectory = api_get_path(SYS_ARCHIVE_PATH);
$files = $_FILES['files'];
$fileList = [];
foreach ($files as $name => $array) {
$counter = 0;
foreach ($array as $data) {
$fileList[$counter][$name] = $data;
$counter++;
}
}
if (!empty($fileList)) {
foreach ($fileList as $n => $file) {
$tmpFile = disable_dangerous_file(
api_replace_dangerous_char($file['name'])
);
file_put_contents(
$tempDirectory.$tmpFile,
fopen($file['tmp_name'], 'r'),
FILE_APPEND
);
}
}
}
echo json_encode([
'files' => $_FILES,
'errorStatus' => 0,
]);
exit;
} else {
$workId = isset($_REQUEST['id']) ? $_REQUEST['id'] : '';
$workInfo = get_work_data_by_id($workId);
$sessionId = api_get_session_id();
$userId = api_get_user_id();
$groupId = api_get_group_id();
$onlyOnePublication = api_get_configuration_value('allow_only_one_student_publication_per_user');
if ($onlyOnePublication) {

@ -12,6 +12,8 @@
* @todo test and reorganise
*/
use enshrined\svgSanitize\Sanitizer;
/**
* Changes the file name extension from .php to .phps
* Useful for securing a site.
@ -28,7 +30,7 @@ function php2phps($file_name)
}
/**
* Renames .htaccess & .HTACCESS to htaccess.txt.
* Renames .htaccess & .HTACCESS & .htAccess to htaccess.txt.
*
* @param string $filename
*
@ -36,7 +38,7 @@ function php2phps($file_name)
*/
function htaccess2txt($filename)
{
return str_replace(['.htaccess', '.HTACCESS'], ['htaccess.txt', 'htaccess.txt'], $filename);
return str_ireplace('.htaccess', 'htaccess.txt', $filename);
}
/**
@ -191,6 +193,22 @@ function process_uploaded_file($uploaded_file, $show_output = true)
return true;
}
function sanitizeSvgFile(string $fullPath)
{
$fileType = mime_content_type($fullPath);
if ('image/svg+xml' !== $fileType) {
return;
}
$svgContent = file_get_contents($fullPath);
$sanitizer = new Sanitizer();
$cleanSvg = $sanitizer->sanitize($svgContent);
file_put_contents($fullPath, $cleanSvg);
}
/**
* This function does the save-work for the documents.
* It handles the uploaded file and adds the properties to the database
@ -394,6 +412,7 @@ function handle_uploaded_document(
$fileExists = file_exists($fullPath);
if (moveUploadedFile($uploadedFile, $fullPath)) {
sanitizeSvgFile($fullPath);
chmod($fullPath, $filePermissions);
if ($fileExists && $docId) {
@ -577,6 +596,7 @@ function handle_uploaded_document(
$filePath = $uploadPath.$fileSystemName;
if (moveUploadedFile($uploadedFile, $fullPath)) {
sanitizeSvgFile($fullPath);
chmod($fullPath, $filePermissions);
// Put the document data in the database
$documentId = add_document(

@ -1689,3 +1689,235 @@ INSERT INTO `extra_field` (`extra_field_type`, `field_type`, `variable`, `displa
*/
//$_configuration['allow_course_multiple_languages'] = false;
// Update user expiration in x days or months when login the first time
/*$_configuration['update_student_expiration_x_date'] = [
'days' => 0,
'months' => 0,
];*/
// Enables to define which user status to show when option is true from $_configuration['user_status_show_option']
//$_configuration['user_status_show_options_enabled'] = false;
// The user status is hidden when is false, it requires $_configuration['user_status_show_options_enabled'] = true
/*$_configuration['user_status_show_option'] = [
'COURSEMANAGER' => true,
'STUDENT' => true,
'DRH' => false,
'SESSIONADMIN' => false,
'STUDENT_BOSS' => false,
'INVITEE' => false
];*/
// Allow learnpath prerequisite on quiz to unblock if maximum attempt is reached
//$_configuration['lp_prerequisit_on_quiz_unblock_if_max_attempt_reached'] = false;
// Enables to hide user status when option is true visible only for admins from $_configuration['user_status_option_show_only_for_admin']
//$_configuration['user_status_option_only_for_admin_enabled'] = false;
// The user status is hidden when is false, it requires $_configuration['user_status_option_only_for_admin_enabled'] = true
/*$_configuration['user_status_option_show_only_for_admin'] = [
'COURSEMANAGER' => false,
'STUDENT' => false,
'DRH' => false,
'SESSIONADMIN' => true,
'STUDENT_BOSS' => false,
'INVITEE' => false
// Set the default expiration date when a user is created by role and days
/*$_configuration['user_number_of_days_for_default_expiration_date_per_role'] = [
'COURSEMANAGER' => 365,
'STUDENT' => 31,
'DRH' => 31,
'SESSIONADMIN' => 60,
'STUDENT_BOSS' => 60,
'INVITEE' => 31
];*/
// Course extra fields to be presented on main/create_course/add_course.php
//$_configuration['course_creation_by_teacher_extra_fields_to_show'] = ['fields' => ['ExtrafieldLabel1', 'ExtrafieldLabel2']];
// Configuration setting to make some extra field required in course creation form.
//$_configuration['course_creation_form_set_extra_fields_mandatory'] = ['fields' => ['fieldLabel1','fieldLabel2']];
// Course extra fields to be presented on course settings
//$_configuration['course_configuration_tool_extra_fields_to_show_and_edit'] = ['fields' => ['ExtrafieldLabel1', 'ExtrafieldLabel2']];
// Relation to prefill course extra field with user extra field on course creacion on main/create_course/add_course.php and main/admin/course_add.php
/*$_configuration['course_creation_user_course_extra_field_relation_to_prefill'] = [
'fields' => [
'CourseExtrafieldLabel1' => 'UserExtrafieldLabel1',
'CourseExtrafieldLabel2' => 'UserExtrafieldLabel2',
]
];*/
// Hides the icon of percentage in "Average of tests in Learning Paths" indication on a student tracking
// $_configuration['student_follow_page_hide_lp_tests_average'] = false;
// Add navigation to the next or previous lp without going to the list.
// Requires DB change:
// ALTER TABLE c_lp ADD next_lp_id int(11) NOT NULL DEFAULT '0';
//$_configuration['lp_enable_flow'] = false;
// User extra fields to be check on user edition to generate a specific process if it was modified
//$_configuration['user_edition_extra_field_to_check'] = 'ExtrafieldLabel';
// Enable skills in subcategory to work independant on assignement
// Require DB changes:
// ALTER TABLE gradebook_category ADD allow_skills_by_subcategory tinyint(1) NULL DEFAULT '1';
// Requires edit Entity GradebookCategory: src/Chamilo/CoreBundle/Entity/GradebookCategory.php uncomment "allowSkillsBySubcategory" variable.
//$_configuration['gradebook_enable_subcategory_skills_independant_assignement'] = false;
// Shows the deleted quizzes in my progress page.
//$_configuration['tracking_my_progress_show_deleted_exercises'] = true;
// Hide IP in exercises reports
// $_configuration['exercise_hide_ip'] = false;
// Enable signature in attendance sheet for users
// Require DB changes:
// ALTER TABLE c_attendance_sheet ADD signature longtext NULL;
// ALTER TABLE c_attendance_calendar ADD blocked tinyint(1) NULL;
// Requires edit Entity CAttendanceSheet : src/Chamilo/CourseBundle/Entity/CAttendanceSheet.php add the @ symbol for attribute $signature into ORM\Column() line.
// Requires edit Entity CAttendanceCalendar : src/Chamilo/CourseBundle/Entity/CAttendanceCalendar.php add the @ symbol for attribute $blocked into ORM\Column() line.
//$_configuration['enable_sign_attendance_sheet'] = false;
// Make sessions by duration always accessible to coaches (otherwise
// they are only accessible during the active duration).
//$_configuration['session_coach_access_after_duration_end'] = false;
// Restrict the list of students to subscribe in the course session. And disable
// registration for users in all courses from Resume Session page
//$_configuration['session_course_users_subscription_limited_to_session_users'] = false;
// Disable tab to add classes in course session for non-admins
//$_configuration['session_classes_tab_disable'] = false;
// Disable the possibility for teachers to edit course visibility
//$_configuration['course_visibility_change_only_admin'] = false;
// Allow DRH user to access all students from reporting.
// $_configuration['drh_allow_access_to_all_students'] = false;
// Disable links in gradebook view for students
// $_configuration['gradebook_hide_link_to_item_for_student'] = false;
// It adds option to define if a document can be downloaded or not.
// Create a document extra field with field label "can_be_downloaded" of type "Checkbox options".
// $_configuration['documents_hide_download_icon'] = false;
// Add the username value to the "subscription to session" confirmation email
//$_configuration['email_template_subscription_to_session_confirmation_username'] = false;
// Add the "remember password" link to the "subscription to session" confirmation email
//$_configuration['email_template_subscription_to_session_confirmation_lost_password'] = false;
// Add a custom extra footer for notificacions emails for a specific language, for example for
// privacy policy notices. Multiple languages and paragraphs can be added.
/*$_configuration['notifications_extended_footer_message'] = ['english' => ['paragraphs' => [
'Change or delete this paragraph or add another one'
]]];*/
// Option to define duration for a calendar in attendance sheet.
// Create an attendance calendar extra field with field label "duration" of type "text".
// $_configuration['attendance_calendar_set_duration'] = false;
// Enable comments in attendance sheet for users
// Require DB changes:
//CREATE TABLE c_attendance_result_comment (iid int not null PRIMARY KEY AUTO_INCREMENT, attendance_sheet_id int not null, user_id int not null, created_at datetime not null, updated_at datetime not null, comment text not null, author_user_id int not null);
//CREATE INDEX c_attendance_sheet_user ON track_e_access_complete (attendance_sheet_id, user_id);
// Then add the "@" symbol to CAttendanceResultComment class in the ORM\Entity() line.
//$_configuration['attendance_allow_comments'] = false;
// Enable categories in Wiki tool.
// 1. Run the following DB changes:
/*
CREATE TABLE c_wiki_rel_category (wiki_id INT NOT NULL, category_id INT NOT NULL, INDEX IDX_AC88945BAA948DBE (wiki_id), INDEX IDX_AC88945B12469DE2 (category_id), PRIMARY KEY(wiki_id, category_id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
CREATE TABLE c_wiki_category (id INT AUTO_INCREMENT NOT NULL, c_id INT NOT NULL, session_id INT DEFAULT NULL, tree_root INT DEFAULT NULL, parent_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, lft INT NOT NULL, lvl INT NOT NULL, rgt INT NOT NULL, INDEX IDX_17F1099A91D79BD3 (c_id), INDEX IDX_17F1099A613FECDF (session_id), INDEX IDX_17F1099AA977936C (tree_root), INDEX IDX_17F1099A727ACA70 (parent_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
ALTER TABLE c_wiki_rel_category ADD CONSTRAINT FK_AC88945BAA948DBE FOREIGN KEY (wiki_id) REFERENCES c_wiki (iid) ON DELETE CASCADE;
ALTER TABLE c_wiki_rel_category ADD CONSTRAINT FK_AC88945B12469DE2 FOREIGN KEY (category_id) REFERENCES c_wiki_category (id) ON DELETE CASCADE;
ALTER TABLE c_wiki_category ADD CONSTRAINT FK_17F1099A91D79BD3 FOREIGN KEY (c_id) REFERENCES course (id) ON DELETE CASCADE;
ALTER TABLE c_wiki_category ADD CONSTRAINT FK_17F1099A613FECDF FOREIGN KEY (session_id) REFERENCES session (id) ON DELETE CASCADE;
ALTER TABLE c_wiki_category ADD CONSTRAINT FK_17F1099AA977936C FOREIGN KEY (tree_root) REFERENCES c_wiki_category (id) ON DELETE CASCADE;
ALTER TABLE c_wiki_category ADD CONSTRAINT FK_17F1099A727ACA70 FOREIGN KEY (parent_id) REFERENCES c_wiki_category (id) ON DELETE CASCADE;
*/
// 2. Add an "@" before "ORM\ManyToMany" and "@ORM\JoinTable" in the "CWiki::$categories" property definition (in src/Chamilo/CourseBundle/Entity/CWiki.php)
// 3. Add an "@" before "ORM\Entity" in the "CWikiCategory" class definition (in src/Chamilo/CourseBundle/Entity/CWikiCategory.php)
//$_configuration['wiki_categories_enabled'] = false;
// Relation to prefill session extra field with user extra field on session creation on main/session/session_add.php
/*$_configuration['session_creation_user_course_extra_field_relation_to_prefill'] = [
'fields' => [
'client' => 'client',
'region' => 'region',
]
];*/
// It adds option to define prerequisites with start and end dates for learnpath items.
// Requires DB changes:
/*
INSERT INTO extra_field (extra_field_type, field_type, variable, display_text, default_value, field_order, visible_to_self, visible_to_others, changeable, filter, created_at) VALUES
(7, 7, 'start_date', 'StartDate', '', 0, 1, 0, 1, 0, NOW());
INSERT INTO extra_field (extra_field_type, field_type, variable, display_text, default_value, field_order, visible_to_self, visible_to_others, changeable, filter, created_at) VALUES
(7, 7, 'end_date', 'EndDate', '', 0, 1, 0, 1, 0, NOW());
*/
//$_configuration['lp_item_prerequisite_dates'] = false;
// Configuration setting to make some extra field required in session creation form on main/session/session_add.php.
// $_configuration['session_creation_form_set_extra_fields_mandatory'] = ['fields' => ['client','region']];
// Ask REST webservices (v2.php) to return another identifier for fields related to user ID.
// This is useful if the external system doesn't really deal with user IDs as they are in Chamilo, as it helps
// the external system match the user data return with some external data that is know to Chamilo. For example, if
// you use an external authentication system, you can return the extra field used to match the user with the
// external authentication system rather than user.id.
// $_configuration['webservice_return_user_field'] = 'oauth2_id';
// Add support for careers hierarchy - refs BT#20711
// 1. This requires the following DB change:
// ALTER TABLE career add parent_id INT
// ALTER TABLE career add constraint career_career_id_fk foreign key (parent_id) references career (id);
// 2. Add an "@" before "var int" and "ORM\Column..." in the "Career::$parentId" property definition (in src/Chamilo/CoreBundle/Entity/Career.php)
// 3. Uncomment $parentId var in src/Chamilo/CoreBundle/Entity/Career.php
// $_configuration['career_hierarchy_enable'] = false;
// KEEP THIS AT THE END
// -------- Custom DB changes
// Set to true to hide settings completely in a sub-URL if the setting is disabled in the
// main URL (where the access_url_changeable field = 0)
// $_configuration['multiple_url_hide_disabled_settings'] = false;
// List of learner certificates - User extra fields to include at the exported CSV as columns
//$_configuration['certificate_export_report_user_extra_fields'] = ['extra_fields' => ['office_address', 'office_phone_extension']];
// Only courses with this option will be visible in catalogue
// Requires DB changes:
/*
INSERT INTO extra_field (extra_field_type, field_type, variable, display_text, default_value, field_order, visible_to_self, visible_to_others, changeable, filter, created_at) VALUES
(2, 3, 'show_in_catalogue', 'Show in catalogue', '', 0, 1, 1, 1, 0, NOW());
SET @ef_id = LAST_INSERT_ID();
INSERT INTO extra_field_options (field_id, option_value, display_text, priority, priority_message, option_order) VALUES
(@ef_id, '1', 'Yes', NULL, NULL, 1),
(@ef_id, '0', 'No', NULL, NULL, 2);
*/
//$_configuration['show_courses_in_catalogue'] = false;
// Allows defining one or several categories of courses that will be visible in the course catalog
// $_configuration['courses_catalogue_show_only_category'] = ['Cat1','Cat2'];
//Hides the link to the course catalog in the menu when the catalog is public.
// $_configuration['catalog_hide_public_link'] = false;
// Display the Portal News link in the admin page to session admin users
//$_configuration['session_admin_access_system_announcement'] = false;
// File upload size limit in MB for teachers (set to 1024 for 1GB, 5120 for 5GB, etc).
//$_configuration['file_upload_size_limit_for_teacher'] = 0;
// Add user activation by confirmation email
// This option prevents the new user to login in the platform if your account is not confirmed via email
// You need add a new option called "confirmation" to the registration settings
//INSERT INTO settings_options (variable, value, display_text) VALUES ('allow_registration', 'confirmation', 'MailConfirmation');
// Enable use of a custom course logo in mail & PDF headers
// $_configuration['mail_header_from_custom_course_logo'] = false;
// Enable additional_webservices.php for *remote* PPT2PNG/Oogie service
//$_configuration['webservice_remote_ppt2png_enable'] = false;

@ -95,8 +95,8 @@ abstract class OpenofficeDocument extends learnpath
if (!empty($size)) {
list($w, $h) = explode('x', $size);
if (!empty($w) && !empty($h)) {
$this->slide_width = $w;
$this->slide_height = $h;
$this->slide_width = (int) $w;
$this->slide_height = (int) $h;
}
}
@ -132,6 +132,7 @@ abstract class OpenofficeDocument extends learnpath
$files = [];
$return = 0;
$cmd = escapeshellcmd($cmd);
$shell = exec($cmd, $files, $return);
if ($return != 0) { // If the java application returns an error code.
@ -237,7 +238,9 @@ abstract class OpenofficeDocument extends learnpath
$cmd .= ' -p '.api_get_setting('service_ppt2lp', 'port');
// Call to the function implemented by child.
$cmd .= ' "'.$this->base_work_dir.'/'.$this->file_path.'" "'.$this->base_work_dir.'/'.$this->created_dir.'"';
$cmd .= ' "'.Security::sanitizeExecParam($this->base_work_dir.'/'.$this->file_path)
.'" "'
.Security::sanitizeExecParam($this->base_work_dir.'/'.$this->created_dir).'"';
// To allow openoffice to manipulate docs.
@chmod($this->base_work_dir, $permissionFolder);
@chmod($this->base_work_dir.'/'.$this->file_path, $permissionFile);
@ -247,6 +250,7 @@ abstract class OpenofficeDocument extends learnpath
$files = [];
$return = 0;
$cmd = escapeshellcmd($cmd);
$shell = exec($cmd, $files, $return);
// TODO: Chown is not working, root keep user privileges, should be www-data
@chown($this->base_work_dir.'/'.$this->created_dir, 'www-data');

@ -241,16 +241,22 @@ class OpenofficePresentation extends OpenofficeDocument
public function add_command_parameters()
{
if (empty($this->slide_width) || empty($this->slide_height)) {
list($this->slide_width, $this->slide_height) = explode('x', api_get_setting('service_ppt2lp', 'size'));
list($w, $h) = explode('x', api_get_setting('service_ppt2lp', 'size'));
$this->slide_width = (int) $w;
$this->slide_height = (int) $h;
}
return ' -w '.$this->slide_width.' -h '.$this->slide_height.' -d oogie "'.$this->base_work_dir.'/'.$this->file_path.'" "'.$this->base_work_dir.$this->created_dir.'.html"';
return ' -w '.$this->slide_width.' -h '.$this->slide_height.' -d oogie '
.Security::sanitizeExecParam($this->base_work_dir.'/'.$this->file_path)
.' '
.Security::sanitizeExecParam($this->base_work_dir.$this->created_dir.'.html');
}
public function set_slide_size($width, $height)
{
$this->slide_width = $width;
$this->slide_height = $height;
$this->slide_width = (int) $width;
$this->slide_height = (int) $height;
}
public function add_docs_to_visio($files = [])

@ -331,7 +331,10 @@ class OpenofficeText extends OpenofficeDocument
*/
public function add_command_parameters()
{
return ' -d woogie "'.$this->base_work_dir.'/'.$this->file_path.'" "'.$this->base_work_dir.$this->created_dir.'/'.$this->file_name.'.html"';
return ' -d woogie '
.Security::sanitizeExecParam($this->base_work_dir.'/'.$this->file_path)
.' '
.Security::sanitizeExecParam($this->base_work_dir.$this->created_dir.'/'.$this->file_name.'.html');
}
/**

@ -333,7 +333,10 @@ class OpenOfficeTextDocument extends OpenofficeDocument
*/
public function add_command_parameters()
{
return ' -d woogie "'.$this->base_work_dir.'/'.$this->file_path.'" "'.$this->base_work_dir.$this->created_dir.'/'.$this->file_name.'.html"';
return ' -d woogie '
.Security::sanitizeExecParam($this->base_work_dir.'/'.$this->file_path)
.' '
.Security::sanitizeExecParam($this->base_work_dir.$this->created_dir.'/'.$this->file_name.'.html');
}
/**

@ -168,9 +168,14 @@ if (isset($_POST['formSent']) && $_POST['formSent']) {
// Looking up for the teacher.
$username = trim(api_utf8_decode($courseNode->CourseTeacher));
$sql = "SELECT user_id, lastname, firstname FROM $tbl_user WHERE username='$username'";
$rs = Database::query($sql);
list($user_id, $lastname, $firstname) = Database::fetch_array($rs);
$rs = Database::select(
['user_id', 'lastname', 'firstname'],
$tbl_user,
['where' => ['username = ?' => $username]],
'first',
'NUM'
);
list($user_id, $lastname, $firstname) = $rs;
$params['teachers'] = $user_id;
CourseManager::create_course($params);

@ -7,6 +7,14 @@
*/
require_once __DIR__.'/../inc/global.inc.php';
$enableThis = api_get_configuration_value('webservice_remote_ppt2png_enable');
if (!$enableThis) {
echo "Remote PPT2PNG service is disabled. \n";
echo "To enable, add \$_configuration['webservice_remote_ppt2png_enable'] = true; to your configuration.php";
exit;
}
api_protect_webservices();
/**
* Function to convert from ppt to png
* This function is used from Chamilo Rapid Lesson.
@ -28,18 +36,26 @@ function wsConvertPpt($pptData)
}
$fileData = $pptData['file_data'];
// Clean filename to avoid hacks. Prevents "&" and ";" to be used in filename, notably
$sanitizedFileName = Security::sanitizeExecParam($pptData['file_name']);
if (strpos($pptData['file_name'], '..') !== false) {
return false;
}
$sanitizedFileName = $pptData['file_name'];
$dataInfo = pathinfo($sanitizedFileName);
$fileName = basename($sanitizedFileName, '.'.$dataInfo['extension']);
// Add additional cleaning of .php and .htaccess files
$fullFileName = Security::filter_filename($sanitizedFileName);
$size = Security::sanitizeExecParam($pptData['service_ppt2lp_size']);
$size = $pptData['service_ppt2lp_size'];
$w = '800';
$h = '600';
if (!empty($size)) {
list($w, $h) = explode('x', $size);
}
$w = (int) $w;
$h = (int) $h;
$tempArchivePath = api_get_path(SYS_ARCHIVE_PATH);
$tempPath = $tempArchivePath.'wsConvert/'.$fileName.'/';
$tempPathNewFiles = $tempArchivePath.'wsConvert/'.$fileName.'-n/';
@ -54,8 +70,12 @@ function wsConvertPpt($pptData)
$file = base64_decode($fileData);
file_put_contents($tempPath.$fullFileName, $file);
$cmd = pptConverterGetCommandBaseParams();
$cmd .= ' -w '.$w.' -h '.$h.' -d oogie "'.$tempPath.$fullFileName.'" "'.$tempPathNewFiles.$fileName.'.html"';
$cmd = pptConverterGetCommandBaseParams(
$w,
$h,
$tempPath.$fullFileName,
$tempPathNewFiles.$fileName.'.html'
);
//$perms = api_get_permissions_for_new_files();
chmod($tempPathNewFiles.$fileName, $perms);
@ -135,21 +155,27 @@ function pptConverterDirectoriesCreate($tempPath, $tempPathNewFiles, $fileName,
*
* @return string $cmd
*/
function pptConverterGetCommandBaseParams()
function pptConverterGetCommandBaseParams(int $w, int $h, string $inputPath, string $outputPath)
{
$cd = '';
if (IS_WINDOWS_OS) { // IS_WINDOWS_OS has been defined in main_api.lib.php
$converterPath = str_replace('/', '\\', api_get_path(SYS_PATH).'main/inc/lib/ppt2png');
$classPath = $converterPath.';'.$converterPath.'/jodconverter-2.2.2.jar;'.$converterPath.'/jodconverter-cli-2.2.2.jar';
$cmd = 'java -Dfile.encoding=UTF-8 -cp "'.$classPath.'" DokeosConverter';
$cmd = 'java -Dfile.encoding=UTF-8 -cp "'.$classPath.'"';
} else {
$converterPath = api_get_path(SYS_PATH).'main/inc/lib/ppt2png';
$classPath = ' -Dfile.encoding=UTF-8 -cp .:jodconverter-2.2.2.jar:jodconverter-cli-2.2.2.jar';
$cmd = 'cd '.$converterPath.' && java '.$classPath.' DokeosConverter';
$cd = 'cd '.$converterPath.' && ';
$cmd = 'java '.$classPath;
}
$cmd .= ' DokeosConverter';
$cmd .= ' -p '.api_get_setting('service_ppt2lp', 'port');
$cmd .= ' -w '.$w.' -h '.$h;
$cmd .= ' -d oogie '.Security::sanitizeExecParam($inputPath).' '.Security::sanitizeExecParam($outputPath);
return $cmd;
return $cd.escapeshellcmd($cmd);
}
$webPath = api_get_path(WEB_PATH);

Loading…
Cancel
Save