Skip to content

Commit

Permalink
Merge branch 'master' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
olleharstedt committed Nov 5, 2021
2 parents 88c66be + 3b88a23 commit 0197dd1
Show file tree
Hide file tree
Showing 46 changed files with 1,599 additions and 512 deletions.
4 changes: 2 additions & 2 deletions application/config/version.php
Expand Up @@ -12,9 +12,9 @@
*/

$config['versionnumber'] = '5.2.0-dev';
$config['dbversionnumber'] = 476;
$config['dbversionnumber'] = 477;
$config['buildnumber'] = '';
$config['updatable'] = true;
$config['templateapiversion'] = 3;
$config['assetsversionnumber'] = '30243';
$config['assetsversionnumber'] = '30244';
return $config;
46 changes: 32 additions & 14 deletions application/controllers/SurveyAdministrationController.php
Expand Up @@ -243,10 +243,13 @@ public function actionDeleteMultiple()
$aSurveys = json_decode(Yii::app()->request->getPost('sItems'));
$aResults = array();
foreach ($aSurveys as $iSurveyID) {
$oSurvey = Survey::model()->findByPk($iSurveyID);
$aResults[$iSurveyID]['title'] = $oSurvey->correct_relation_defaultlanguage->surveyls_title;
if (Permission::model()->hasSurveyPermission($iSurveyID, 'survey', 'delete')) {
$oSurvey = Survey::model()->findByPk($iSurveyID);
$aResults[$iSurveyID]['title'] = $oSurvey->correct_relation_defaultlanguage->surveyls_title;
$aResults[$iSurveyID]['result'] = Survey::model()->deleteSurvey($iSurveyID);
} else {
$aResults[$iSurveyID]['result'] = false;
$aResults[$iSurveyID]['error'] = gT("User does not have valid permissions");
}
}
$this->renderPartial(
Expand All @@ -272,11 +275,9 @@ public function actionRenderItemsSelected()
if (!is_numeric($iSurveyID)) {
continue;
}
if (Permission::model()->hasSurveyPermission($iSurveyID, 'survey', 'delete')) {
$oSurvey = Survey::model()->findByPk($iSurveyID);
$aResults[$iSurveyID]['title'] = $oSurvey->correct_relation_defaultlanguage->surveyls_title;
$aResults[$iSurveyID]['result'] = 'selected';
}
$oSurvey = Survey::model()->findByPk($iSurveyID);
$aResults[$iSurveyID]['title'] = $oSurvey->correct_relation_defaultlanguage->surveyls_title;
$aResults[$iSurveyID]['result'] = 'selected';
}

$this->renderPartial(
Expand Down Expand Up @@ -779,7 +780,7 @@ public function actionGetCurrentEditorValues($sid)
public function actionChangeMultipleTheme()
{
//only superadmin can do this
if (!Permission::model()->hasGlobalPermission('superadmin', 'update')) {
if (!Yii::app()->request->isPostRequest && !Permission::model()->hasGlobalPermission('superadmin', 'update')) {
Yii::app()->user->setFlash('error', gT("Access denied"));
$this->redirect(Yii::app()->request->urlReferrer);
}
Expand Down Expand Up @@ -809,7 +810,7 @@ public function actionChangeMultipleTheme()
*/
public function actionChangeMultipleSurveyGroup()
{
if (!Permission::model()->hasGlobalPermission('superadmin', 'update')) {
if (!Yii::app()->request->isPostRequest && !Permission::model()->hasGlobalPermission('superadmin', 'update')) {
Yii::app()->user->setFlash('error', gT("Access denied"));
$this->redirect(Yii::app()->request->urlReferrer);
}
Expand All @@ -824,7 +825,17 @@ public function actionChangeMultipleSurveyGroup()
$oSurvey = Survey::model()->findByPk((int)$iSurveyID);
$oSurvey->gsid = $iSurveyGroupId;
$aResults[$iSurveyID]['title'] = $oSurvey->correct_relation_defaultlanguage->surveyls_title;
$aResults[$iSurveyID]['result'] = $oSurvey->save();
if (!Permission::model()->hasGlobalPermission('superadmin', 'update')) {
$aResults[$iSurveyID]['result'] = false;
$aResults[$iSurveyID]['error'] = gT("User does not have valid permissions");
} else {
if ($oSurvey->save()) {
$aResults[$iSurveyID]['result'] = true;
} else {
$aResults[$iSurveyID]['result'] = false;
$aResults[$iSurveyID]['error'] = gT("Survey update failed");
}
}
}

Yii::app()->getController()->renderPartial(
Expand Down Expand Up @@ -2330,7 +2341,7 @@ public function actionDatetimesettings()
public function actionExpireMultipleSurveys()
{
//permission check: only superadmin is allowed to do this
if (!Permission::model()->hasGlobalPermission('superadmin')) {
if (!Yii::app()->request->isPostRequest && !Permission::model()->hasGlobalPermission('superadmin')) {
Yii::app()->user->setFlash('error', gT("Access denied"));
$this->redirect(Yii::app()->request->urlReferrer);
}
Expand All @@ -2352,10 +2363,16 @@ public function actionExpireMultipleSurveys()
$survey = Survey::model()->findByPk($sid);
$survey->expires = $expires;
$aResults[$survey->primaryKey]['title'] = ellipsize($survey->correct_relation_defaultlanguage->surveyls_title, 30);
if ($survey->save()) {
$aResults[$survey->primaryKey]['result'] = true;
} else {
if (!Permission::model()->hasGlobalPermission('superadmin')) {
$aResults[$survey->primaryKey]['result'] = false;
$aResults[$survey->primaryKey]['error'] = gT("User does not have valid permissions");
} else {
if ($survey->save()) {
$aResults[$survey->primaryKey]['result'] = true;
} else {
$aResults[$survey->primaryKey]['result'] = false;
$aResults[$survey->primaryKey]['error'] = gT("Survey update failed");
}
}
}
$this->renderPartial(
Expand Down Expand Up @@ -2619,6 +2636,7 @@ public function changeTemplate($iSurveyID, $template, $aResults = null, $bReturn
if (!empty($bReturn)) {
$aResults[$iSurveyID]['title'] = $survey->correct_relation_defaultlanguage->surveyls_title;
$aResults[$iSurveyID]['result'] = false;
$aResults[$iSurveyID]['error'] = gT("User does not have valid permissions");
return $aResults;
} else {
die('No permission');
Expand Down
13 changes: 9 additions & 4 deletions application/controllers/admin/themes.php
Expand Up @@ -240,7 +240,8 @@ protected function uploadTemplateImageFile(string $sTemplateName)
}

$destdir = $oTemplateConfiguration->filesPath;
if (Template::isStandardTemplate($oTemplateConfiguration->sTemplateName)) {
Yii::import('application.helpers.SurveyThemeHelper');
if (SurveyThemeHelper::isStandardTemplate($oTemplateConfiguration->sTemplateName)) {
$destdir = $oTemplateConfiguration->generalFilesPath;
}

Expand Down Expand Up @@ -689,7 +690,8 @@ public function templatecopy()
if (Permission::model()->hasGlobalPermission('templates', 'create')) {
$newname = sanitize_dirname(Yii::app()->request->getPost("newname"));

if (Template::isStandardTemplate($newname)) {
Yii::import('application.helpers.SurveyThemeHelper');
if(SurveyThemeHelper::isStandardTemplate($newname)){
Yii::app()->setFlashMessage(sprintf(gT("Directory with the name `%s` already exists - choose another name"), $newname), 'error');
$this->getController()->redirect(array("themeOptions/index"));
}
Expand Down Expand Up @@ -739,7 +741,9 @@ public function delete()
if (Permission::model()->hasGlobalPermission('templates', 'delete')) {
Yii::app()->loadHelper("admin/template");

if (Template::checkIfTemplateExists($templatename) && !Template::isStandardTemplate($templatename)) {
Yii::import('application.helpers.SurveyThemeHelper');
if (Template::checkIfTemplateExists($templatename) && !SurveyThemeHelper::isStandardTemplate($templatename)) {

if (!Template::hasInheritance($templatename)) {
if (rmdirr(Yii::app()->getConfig('userthemerootdir') . "/" . $templatename)) {
Template::model()->findByPk($templatename)->deleteAssetVersion();
Expand Down Expand Up @@ -811,7 +815,8 @@ public function deleteAvailableTheme()
throw new CHttpException(403, "Disable for security reasons.");
}
// CheckIfTemplateExists check if the template is installed....
if (! Template::checkIfTemplateExists($templatename) && !Template::isStandardTemplate($templatename)) {
Yii::import('application.helpers.SurveyThemeHelper');
if (! Template::checkIfTemplateExists($templatename) && !SurveyThemeHelper::isStandardTemplate($templatename)) {
if (rmdirr(Yii::app()->getConfig('userthemerootdir') . "/" . $templatename)) {
Yii::app()->setFlashMessage(sprintf(gT("Theme '%s' was successfully deleted."), $templatename));
} else {
Expand Down
16 changes: 14 additions & 2 deletions application/controllers/admin/tokens.php
Expand Up @@ -609,6 +609,14 @@ public function addnew(int $iSurveyId)

$aData['topBar']['name'] = 'tokensTopbar_view';

if ($aData['success']) {
if ($request->getPost('close-after-save')) {
$redirectUrl = Yii::app()->createUrl('admin/tokens/sa/browse/surveyid/' . $iSurveyId);
} else {
$redirectUrl = Yii::app()->createUrl("/admin/tokens/sa/edit", ["iSurveyId" => $iSurveyId, "iTokenId" => $token->tid]);
}
$this->getController()->redirect($redirectUrl);
}
$this->_renderWrappedTemplate('token', array('addtokenpost'), $aData);
} else {
$this->_handletokenform($iSurveyId, "addnew");
Expand Down Expand Up @@ -721,6 +729,10 @@ public function edit($iSurveyId, $iTokenId, $ajax = false)
$aTokenData[$attr_name] = $request->getPost($attr_name);
}

if (!empty($sOutput)) {
\ls\ajax\AjaxHelper::outputError($sOutput);
}

$token = Token::model($iSurveyId)->findByPk($iTokenId);
$token->decrypt();
foreach ($aTokenData as $k => $v) {
Expand All @@ -730,7 +742,7 @@ public function edit($iSurveyId, $iTokenId, $ajax = false)
$result = $token->encryptSave(true);

if ($result) {
\ls\ajax\AjaxHelper::outputSuccess($sOutput . gT('The survey participant was successfully updated.'));
\ls\ajax\AjaxHelper::outputSuccess(gT('The survey participant was successfully updated.'));
} else {
$errors = $token->getErrors();
$firstError = reset($errors);
Expand Down Expand Up @@ -2468,7 +2480,7 @@ public function _handletokenform($iSurveyId, $subaction, $iTokenId = "", $ajax =
$aData['showSaveAndCloseButton'] = true;
// White Close Button
$aData['showWhiteCloseButton'] = true;
$aData['closeUrl'] = Yii::app()->createUrl('admin/tokens/sa/index/surveyid/' . $iSurveyId);
$aData['closeUrl'] = Yii::app()->createUrl('admin/tokens/sa/browse/surveyid/' . $iSurveyId);

$aData['topBar']['name'] = 'tokensTopbar_view';
$aData['topBar']['rightSideView'] = 'tokensTopbarRight_view';
Expand Down
6 changes: 6 additions & 0 deletions application/controllers/survey/index.php
Expand Up @@ -37,7 +37,13 @@ public function action()
$surveyid = $param['sid'];
$thisstep = $param['thisstep'];
$move = getMove();

/* Get client token by POST or GET value */
$clienttoken = trim($param['token']);
/* If not set : get by SESSION to avoid multiple submit of same token in different navigator */
if(empty($clienttoken) && !empty($_SESSION['survey_' . $surveyid]['token'] )) {
$clienttoken = $_SESSION['survey_' . $surveyid]['token'];
}

$oSurvey = Survey::model()->findByPk($surveyid);

Expand Down
31 changes: 19 additions & 12 deletions application/core/LS_Twig_Extension.php
Expand Up @@ -287,20 +287,27 @@ public static function image($sImagePath, $alt = '', $htmlOptions = array( ))
*/
public static function imageSrc($sImagePath, $default = false)
{
// Reccurence on templates to find the file
$oTemplate = self::getTemplateForRessource($sImagePath);
$sUrlImgAsset = $sImagePath;

if ($oTemplate) {
$sFullPath = $oTemplate->path . $sImagePath;
// If $sImagePath is a 'virtual' path, we must get the real path.
if (preg_match('/(image::\w+::)/', $sImagePath, $m)) {
$oTemplate = Template::getLastInstance();
Yii::import('application.helpers.SurveyThemeHelper');
$sFullPath = SurveyThemeHelper::getRealThemeFilePath($sImagePath, $oTemplate->template_name, $oTemplate->sid);
} else {
if (!is_file(Yii::app()->getConfig('rootdir') . '/' . $sImagePath)) {
if ($default) {
return self::imageSrc($default);
}
return false;
// If it's not a virtual path, only paths relative to a theme (and within the theme) are allowed.
// Recurrence on templates to find the file
$oTemplate = self::getTemplateForRessource($sImagePath);
$sUrlImgAsset = $sImagePath;

if ($oTemplate) {
$sFullPath = $oTemplate->path.$sImagePath;
}
$sFullPath = Yii::app()->getConfig('rootdir') . '/' . $sImagePath;
}

if (empty($sFullPath)) {
if($default) {
return self::imageSrc($default);
}
return false;
}

// check if this is a true image
Expand Down
40 changes: 40 additions & 0 deletions application/datavalueobjects/ThemeFileCategory.php
@@ -0,0 +1,40 @@
<?php

namespace LimeSurvey\Datavalueobjects;

/**
* Class ThemeFileCategory
*
* This class represents a theme file category (eg. Global files, Theme files, Survey files)
*
* @package LimeSurvey\DataValueObject
*/
class ThemeFileCategory
{

/** @var string the category name */
public $name;

/** @var string the display title for the category */
public $title;

/** @var string the base path for the category */
public $path;

/** @var string the "virtual" path prefix (eg. 'image::generalfiles::') */
public $pathPrefix;

/**
* @param string $name
* @param string $title
* @param string $path
* @param string $pathPrefix
*/
public function __construct($name, $title, $path, $pathPrefix)
{
$this->name = $name;
$this->title = $title;
$this->path = $path;
$this->pathPrefix = $pathPrefix;
}
}
44 changes: 44 additions & 0 deletions application/datavalueobjects/ThemeFileInfo.php
@@ -0,0 +1,44 @@
<?php

namespace LimeSurvey\Datavalueobjects;

/**
* Class ThemeFileInfo
*
* This class represents a theme file. It includes the real path, the virtual path, and the category.
*
* Virtual paths are a special notation for relative paths, including a prefix to give context.
* Eg.: the path "image::theme::files/logo.png" is relative to the theme folder, while
* "image::generalfiles::" is relative to the general files folder.
* If $path is not valid, returns null.
* Paths can be
* - related to a global theme option and hence the file be located on the generalfiles directory.
* - related to a survey theme option and hence the file be located relative to a survey upload directory.
* - related to a theme and hence the file be located on the theme directory (eg. when uploaded from theme editor)
*
* @package LimeSurvey\DataValueObject
*/
class ThemeFileInfo
{

/** @var string the real path to the file (eg. '/var/www/html/limesurvey/themes/survey/vanilla/files/logo.png') */
public $realPath;

/** @var string the virtual path to the file (eg. 'image::theme::logo.png') */
public $virtualPath;

/** @var ThemeFileCategory */
public $category;

/**
* @param string $realPath
* @param string $virtualPath
* @param ThemeFileCategory $category
*/
public function __construct($realPath, $virtualPath, $category)
{
$this->realPath = $realPath;
$this->virtualPath = $virtualPath;
$this->category = $category;
}
}
11 changes: 8 additions & 3 deletions application/helpers/SurveyRuntimeHelper.php
Expand Up @@ -540,8 +540,9 @@ public function run($surveyid, $args)
$this->aSurveyInfo['hiddenInputs'] .= \CHtml::hiddenField('start_time', time(), array('id' => 'start_time'));
$_SESSION[$this->LEMsessid]['LEMpostKey'] = isset($_POST['LEMpostKeyPreset']) ? $_POST['LEMpostKeyPreset'] : mt_rand();
$this->aSurveyInfo['hiddenInputs'] .= \CHtml::hiddenField('LEMpostKey', $_SESSION[$this->LEMsessid]['LEMpostKey'], array('id' => 'LEMpostKey'));
if (!empty($_SESSION[$this->LEMsessid]['token'])) {
$this->aSurveyInfo['hiddenInputs'] .= \CHtml::hiddenField('token', $_SESSION[$this->LEMsessid]['token'], array('id' => 'token'));
/* Reset session with multiple tabs (show Token mismatch issue) , but only for not anonymous survey */
if (!empty($_SESSION[$this->LEMsessid]['token']) and $this->aSurveyInfo['anonymized'] != 'Y') {
$this->aSurveyInfo['hiddenInputs'] .= \CHtml::hiddenField('token', $_SESSION[$this->LEMsessid]['token'], array('id'=>'token'));
}
}

Expand Down Expand Up @@ -1442,7 +1443,11 @@ private function getErrorHtmlMessage()

//Mandatory question(s) with unanswered answer
if ($this->aStepInfo['mandViolation'] && $this->okToShowErrors) {
$aErrorsMandatory[] = gT("One or more mandatory questions have not been answered. You cannot proceed until these have been completed.");
if ($this->aStepInfo['mandNonSoft']) {
$aErrorsMandatory[] = gT("One or more mandatory questions have not been answered. You cannot proceed until these have been completed.");
} else {
$aErrorsMandatory[] = gT("One or more mandatory questions have not been answered. If possible, please complete them before continuing to the next page.");
}
}

// Question(s) with not valid answer(s)
Expand Down

0 comments on commit 0197dd1

Please sign in to comment.