diff --git a/CHANGES.MD b/CHANGES.md similarity index 93% rename from CHANGES.MD rename to CHANGES.md index 81d55457..e4de9938 100644 --- a/CHANGES.MD +++ b/CHANGES.md @@ -5,6 +5,15 @@ - Stockage distinct du thème et des autres données (core, config, page, module et users ) avec import des données d'une version 8 - Exporter un thème (avec les images) sous forme d'une archive ZIP à télécharger ou stocker dans Fichiers. - Importer un thème à partir des fichiers + - Deux blocs (colonnes) à droite ou à gauche contenant des informations fixes, le paramétage est dans le thème, mais les contenus sont stockés dans les pages. + - Pas de bloc pour les écrans de configuration. + - Changement du libellé Modérateur devient Editeur +- Correction : + - Faille CSRF lors de l'effacement d'une page + - Faille CSRF lors de l'effacement d'une galerie + - Faille CSRF lors de l'effacement d'un article de blog + - Faille CSRF lors de l'effacement d'un article de news + - Faille CSRF lors de l'effacement d'un membre ## Verison 8.5.3 * Modification : @@ -12,12 +21,12 @@ * Correction : - Appel de la génération de la capture d'écran OpenGraph quand le fichier est absent - CSS pour le footer des blocs et non des éléments - - #footersite, #footerbody : bloc footer dans et hors site - - #footersite, #footerbody a : liens du bloc footer dans et hors site + - \#footersite, \#footerbody : bloc footer dans et hors site + - \#footersite, \#footerbody a : liens du bloc footer dans et hors site - Bloc des colonnes dans et hors site : - - #footersiteLeft, #footerbodyLef - - #footersiteCenter, #footerbodyCenter - - #footersiteRight, #footerbodyRight + - \#footersiteLeft, \#footerbodyLef + - \#footersiteCenter, \#footerbodyCenter + - \#footersiteRight, \#footerbodyRight ## Verison 8.5.2 diff --git a/README.md b/README.md index c3cd60e9..ff5a56f3 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Zwii 9 Béta +# Zwii 9 Bêta Zwii est un CMS sans base de données (Flat-File) qui permet à ses utilisateurs de créer et gérer facilement un site web sans aucune connaissance en programmation. diff --git a/core/core.php b/core/core.php index 12ff46a6..ce33a45f 100644 --- a/core/core.php +++ b/core/core.php @@ -176,6 +176,38 @@ class common { 'group' => self::GROUP_VISITOR, 'targetBlank' => false, 'title' => 'Contact' + ], + 'blockRight' => [ + 'typeMenu' => '', + 'iconUrl' => '', + 'disable' => false, + 'content' => '

Bloc à droite du site

', + 'hideTitle' => false, + 'metaDescription' => '', + 'metaTitle' => '', + 'moduleId' => '', + 'modulePosition' => '', + 'parentPageId' => '', + 'position' => 0, + 'group' => self::GROUP_VISITOR, + 'targetBlank' => false, + 'title' => 'blockRight' + ], + 'blockLeft' => [ + 'typeMenu' => '', + 'iconUrl' => '', + 'disable' => false, + 'content' => '

Bloc à gauche du site

', + 'hideTitle' => false, + 'metaDescription' => '', + 'metaTitle' => '', + 'moduleId' => '', + 'modulePosition' => '', + 'parentPageId' => '', + 'position' => 0, + 'group' => self::GROUP_VISITOR, + 'targetBlank' => false, + 'title' => 'blockLeft' ] ], 'module' => [ @@ -349,7 +381,8 @@ class common { 'backgroundColor' => 'rgba(255, 255, 255, 1)', 'radius' => '0', 'shadow' => '0', - 'width' => '1170px' + 'width' => '960px', + 'blocks' => '100' ], 'text' => [ 'font' => 'Open+Sans', @@ -407,24 +440,24 @@ class common { self::GROUP_BANNED => 'Banni', self::GROUP_VISITOR => 'Visiteur', self::GROUP_MEMBER => 'Membre', - self::GROUP_MODERATOR => 'Modérateur', + self::GROUP_MODERATOR => 'Éditeur', self::GROUP_ADMIN => 'Administrateur' ]; public static $groupEdits = [ self::GROUP_BANNED => 'Banni', self::GROUP_MEMBER => 'Membre', - self::GROUP_MODERATOR => 'Modérateur', + self::GROUP_MODERATOR => 'Éditeur', self::GROUP_ADMIN => 'Administrateur' ]; public static $groupNews = [ self::GROUP_MEMBER => 'Membre', - self::GROUP_MODERATOR => 'Modérateur', + self::GROUP_MODERATOR => 'Éditeur', self::GROUP_ADMIN => 'Administrateur' ]; public static $groupPublics = [ self::GROUP_VISITOR => 'Visiteur', self::GROUP_MEMBER => 'Membre', - self::GROUP_MODERATOR => 'Modérateur', + self::GROUP_MODERATOR => 'Éditeur', self::GROUP_ADMIN => 'Administrateur' ]; public static $timezone; @@ -994,7 +1027,7 @@ class common { } // Version 9.0.0 if($this->getData(['core', 'dataVersion']) < 900) { - + $this->setData(['theme', 'site', 'blocks','100']); $this->setData(['core', 'dataVersion', 900]); $this->SaveData(); } @@ -1898,25 +1931,25 @@ class layout extends common { echo $this->core->output['content']; } - /** - * Affiche le coyright - */ - public function showCopyright() { - $items = '
'; - $items .= 'Motorisé par Zwii'; - $items .= ' | Plan du site'; - if( - ( - $this->getData(['theme', 'footer', 'loginLink']) - AND $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') - ) - OR $this->getUrl(0) === 'theme' - ) { - $items .= 'getUrl(0) === 'theme' ? 'class="displayNone"' : '') . '> | Connexion'; - } - $items .= '
'; - echo $items; - } +/** + * Affiche le copyright + */ + public function showCopyright() { + $items = '
'; + $items .= 'Motorisé par Zwii'; + $items .= ' | Plan du site'; + if( + ( + $this->getData(['theme', 'footer', 'loginLink']) + AND $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') + ) + OR $this->getUrl(0) === 'theme' + ) { + $items .= 'getUrl(0) === 'theme' ? 'class="displayNone"' : '') . '> | Connexion'; + } + $items .= '
'; + echo $items; + } /** * Affiche le favicon @@ -1999,8 +2032,6 @@ class layout extends common { $targetBlank = $this->getData(['page', $childKey, 'targetBlank']) ? ' target="_blank"' : ''; // Mise en page du sous-item - // Menu Image - if ( $this->getData(['page',$childKey,'disable']) === true AND $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') ) @@ -2131,13 +2162,17 @@ class layout extends common { if($this->getUser('group') >= self::GROUP_MODERATOR) { $leftItems .= '
  • '; $leftItems .= '
  • ' . template::ico('plus') . '
  • '; if( diff --git a/core/layout/common.css b/core/layout/common.css index 1f7d7d19..87ad5fb5 100755 --- a/core/layout/common.css +++ b/core/layout/common.css @@ -423,6 +423,15 @@ footer .col4 { footer #footerSocials { font-size: 1.0em; } + +footer #footerSocials { + font-size: 1.0em; +} + +footer #footerCopyright, #footerText { + font-size: 0.8em; +} + footer #footerSocials span { color: #FFF; padding: 9px; diff --git a/core/layout/main.php b/core/layout/main.php index 3a86ee70..ac72294a 100755 --- a/core/layout/main.php +++ b/core/layout/main.php @@ -33,11 +33,9 @@ getData(['theme', 'header', 'position']) === 'body'): ?> - getData(['theme','header','linkHome'])){ echo "" ;} ?> -
    getUrl(0) === 'theme' AND $this->getUrl(1) === 'header') ): ?> - -
    getData(['config', 'title']); ?>
    - - -
    - + getData(['theme','header','linkHome'])){echo "
    ";} - ?> - - + ?> + getData(['theme', 'menu', 'position']) === 'body-second'): ?> - -
    showContent(); ?>
    + getUrl(0) === 'user' OR + $this->getUrl(0) === 'theme' OR + $this->getUrl(0) === 'config' OR + $this->getUrl(0) === 'page' OR + $this->getUrl(1) === 'config' OR + $this->getUrl(1) === 'edit' + ) { ?> +
    showContent(); ?>
    + getData(['theme','site','blocks'])); + $blockleft=$blockright=""; + switch (sizeof($blocks)) { + case 1 : // une colonne + $content = 'col'. $blocks[0] ; + break; + case 2 : // 2 blocks + if ($blocks[0] < $blocks[1]) { // détermine la position de la colonne + $blockleft = 'col'. $blocks[0]; + $content = 'col'. $blocks[1] ; + } else { + $content = 'col' . $blocks[0]; + $blockright = 'col' . $blocks[1]; + } + break; + case 3 : // 3 blocks + $blockleft = 'col' . $blocks[0]; + $content = 'col' . $blocks[1]; + $blockright = 'col' . $blocks[2]; + } + ?> +
    +
    +
    getData(['page','blockLeft','content']);?>
    +
    showContent(); ?>
    +
    getData(['page','blockRight','content']);?>
    +
    +
    + + getData(['theme', 'footer', 'position']) === 'site' // Affiche toujours le pied de page pour l'édition du thème diff --git a/core/module/page/page.php b/core/module/page/page.php index cccf8a38..ae247db6 100755 --- a/core/module/page/page.php +++ b/core/module/page/page.php @@ -17,26 +17,26 @@ class page extends common { public static $actions = [ 'add' => self::GROUP_MODERATOR, 'delete' => self::GROUP_MODERATOR, - 'edit' => self::GROUP_MODERATOR + 'edit' => self::GROUP_MODERATOR, + 'block' => self::GROUP_ADMIN ]; public static $pagesNoParentId = [ '' => 'Aucune' ]; public static $moduleIds = []; - // Menu image public static $typeMenu = [ 'text' => 'Texte', 'icon' => 'Icône', 'icontitle' => 'Icône et bulle' ]; - // menu image // Position du module public static $modulePosition = [ - 'bottom' => 'En bas', - 'top' => 'En haut', - 'free' => 'Libre' + 'bottom' => 'En bas', + 'top' => 'En haut', + 'free' => 'Libre' ]; + /** * Création */ @@ -46,12 +46,10 @@ class page extends common { $this->setData([ 'page', $pageId, - [ - // Menu icon + [ 'typeMenu' => 'text', 'iconUrl' => '', - 'disable' => false, - // Menu icon + 'disable' => false, 'content' => 'Contenu de votre nouvelle page.', 'hideTitle' => false, 'metaDescription' => '', @@ -77,33 +75,50 @@ class page extends common { * Suppression */ public function delete() { + // $url prend l'adresse sans le token + $url = explode('&',$this->getUrl(2)); // La page n'existe pas - if($this->getData(['page', $this->getUrl(2)]) === null) { + if($this->getData(['page', $url[0]]) === null) { // Valeurs en sortie $this->addOutput([ 'access' => false ]); } // Impossible de supprimer la page d'accueil - elseif($this->getUrl(2) === $this->getData(['config', 'homePageId'])) { + elseif($url[0] === $this->getData(['config', 'homePageId'])) { // Valeurs en sortie $this->addOutput([ - 'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2), + 'redirect' => helper::baseUrl() . 'page/edit/' . $url[0], 'notification' => 'Impossible de supprimer la page d\'accueil' ]); } - // Impossible de supprimer une page contenant des enfants - elseif($this->getHierarchy($this->getUrl(2))) { + // Jeton incorrect + elseif(!isset($_GET['csrf'])) { // Valeurs en sortie $this->addOutput([ - 'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2), + 'redirect' => helper::baseUrl() . 'page/edit/' . $url[0], + 'notification' => 'Jeton invalide' + ]); + } + elseif ($_GET['csrf'] !== $_SESSION['csrf']) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'page/edit/' . $url[0], + 'notification' => 'Suppression non autorisée' + ]); + } + // Impossible de supprimer une page contenant des enfants + elseif($this->getHierarchy($url[0])) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'page/edit/' . $url[0], 'notification' => 'Impossible de supprimer une page contenant des enfants' ]); } // Suppression else { - $this->deleteData(['page', $this->getUrl(2)]); - $this->deleteData(['module', $this->getUrl(2)]); + $this->deleteData(['page', $url[0]]); + $this->deleteData(['module', $url[0]]); // Valeurs en sortie $this->addOutput([ 'redirect' => helper::baseUrl(false), @@ -113,6 +128,65 @@ class page extends common { } } + /** + * Édition des blocs + */ + public function block () { + if($this->isPost()) { + $this->setData([ + 'page', + 'blockLeft', [ + 'typeMenu' => 'text', + 'iconUrl' => '', + 'disable' => true, + 'hideTitle' => false, + 'metaDescription' => '', + 'metaTitle' => '', + 'moduleId' => '', + 'parentPageId' => '', + 'modulePosition' => 'bottom', + 'position' => 0, + 'group' => self::GROUP_VISITOR, + 'targetBlank' => false, + 'title' => 'blockLeft', + 'content' => (empty($this->getInput('pageBlockLeftContent', null)) ? "

    " : $this->getInput('pageBlockLeftContent', null))] + ]); + $this->setData([ + 'page', + 'blockRight', [ + 'typeMenu' => 'text', + 'iconUrl' => '', + 'disable' => true, + 'hideTitle' => false, + 'metaDescription' => '', + 'metaTitle' => '', + 'moduleId' => '', + 'parentPageId' => '', + 'modulePosition' => 'bottom', + 'position' => 0, + 'group' => self::GROUP_VISITOR, + 'targetBlank' => false, + 'title' => 'blockRight', + 'content' => (empty($this->getInput('pageBlockRightContent', null)) ? "

    " : $this->getInput('pageBlockRightContent', null))] + ]); + $this->addOutput([ + 'redirect' => helper::baseUrl(), + 'notification' => 'Modifications enregistrées', + 'state' => true + ]); + } + + // Valeurs en sortie + $this->addOutput([ + 'title' => 'Édition des blocs', + 'vendor' => [ + 'tinymce' + ], + 'view' => 'block' + ]); + } + + /** * Édition */ diff --git a/core/module/page/view/block/block.js.php b/core/module/page/view/block/block.js.php new file mode 100644 index 00000000..d21cf5f7 --- /dev/null +++ b/core/module/page/view/block/block.js.php @@ -0,0 +1,102 @@ +/** + * This file is part of Zwii. + * + * For full copyright and license information, please see the LICENSE + * file that was distributed with this source code. + * + * @author Rémi Jean + * @copyright Copyright (C) 2008-2018, Rémi Jean + * @license GNU General Public License, version 3 + * @link http://zwiicms.com/ + */ + +/** + * Confirmation de suppression + */ +$("#pageEditDelete").on("click", function() { + var _this = $(this); + return core.confirm("Êtes-vous sûr de vouloir supprimer cette page ?", function() { + $(location).attr("href", _this.attr("href")); + }); +}); + +/** + * Bloque/Débloque le bouton de configuration au changement de module + */ +var pageEditModuleIdDOM = $("#pageEditModuleId"); +pageEditModuleIdDOM.on("change", function() { + if($(this).val() === "") { + $("#pageEditModuleConfig").addClass("disabled"); + $("#pageEditContentContainer").slideDown(); + } + else { + $("#pageEditModuleConfig").removeClass("disabled"); + $("#pageEditContentContainer").slideUp(); + } +}); + +/** + * Soumission du formulaire pour éditer le module + */ +$("#pageEditModuleConfig").on("click", function() { + $("#pageEditModuleRedirect").val(1); + $("#pageEditForm").trigger("submit"); +}); + +/** + * Affiche les pages en fonction de la page parent dans le choix de la position + */ +var hierarchy = getHierarchy()); ?>; +var pages = getData(['page'])); ?>; +$("#pageEditParentPageId").on("change", function() { + var positionDOM = $("#pageEditPosition"); + positionDOM.empty().append( + $("
    -
    - +
    'Sélectionnez le type de menu.', 'label' => 'Type de menu', @@ -64,7 +63,6 @@ ]); ?>
    - 'Icône', 'value' => $this->getData(['page', $this->getUrl(2), 'iconUrl']) diff --git a/core/module/theme/resource/custom.css b/core/module/theme/resource/custom.css index 872f75c9..55e4f0cd 100755 --- a/core/module/theme/resource/custom.css +++ b/core/module/theme/resource/custom.css @@ -15,6 +15,14 @@ body { #site { } +/* Blocs dans le site */ +#contentleft { +} +#contentright { +} +#contentsite { +} + /* Bannière */ header { } @@ -40,23 +48,26 @@ nav a.active { } /* Bas de page */ -#footersite, #footerbody { +footer { +} + +footer #footersite, #footerbody { } /* Liens du bas de page */ -#footersite, #footerbody a { +footer #footersite, #footerbody a { } /* footer bloc gauche */ -#footersiteLeft, #footerbodyLeft { +footer #footersiteLeft, #footerbodyLeft { } /* footer bloc central */ -#footersiteCenter, #footerbodyCenter { +footer #footersiteCenter, #footerbodyCenter { } /* footer bloc droite */ -#footersiteRight, #footerbodyRight { +footer #footersiteRight, #footerbodyRight { } /** diff --git a/core/module/theme/theme.php b/core/module/theme/theme.php index 7ee58d26..5d4b31c2 100755 --- a/core/module/theme/theme.php +++ b/core/module/theme/theme.php @@ -201,9 +201,18 @@ class theme extends common { 'contain' => 'Image entière', 'cover' => 'Largeur adaptée au fond', '100% 100%' => 'Taille adaptée au fond' - ]; + public static $siteBlocks = [ + '12' => 'Un seul bloc, uniquement le site', + '4-8' => 'Deux blocs : 1/3 - 2/3', + '8-4' => 'Deux blocs : 2/3 - 1/3', + '3-9' => 'Deux blocs : 1/4 - 3/4', + '9-3' => 'Deux blocs : 3/4 - 1/2', + '3-6-3' => 'Trois blocs : 1/4 - 1/2 - 1/4' + ]; + + /** * Mode avancé */ @@ -424,7 +433,8 @@ class theme extends common { 'backgroundColor' => $this->getInput('themeSiteBackgroundColor'), 'radius' => $this->getInput('themeSiteRadius'), 'shadow' => $this->getInput('themeSiteShadow'), - 'width' => $this->getInput('themeSiteWidth') + 'width' => $this->getInput('themeSiteWidth'), + 'blocks' => $this->getInput('themeSiteBlocks') ]]); // Valeurs en sortie $this->addOutput([ @@ -437,7 +447,8 @@ class theme extends common { $this->addOutput([ 'title' => 'Personnalisation du site', 'vendor' => [ - 'tinycolorpicker' + 'tinycolorpicker', + 'tinymce' ], 'view' => 'site' ]); diff --git a/core/module/theme/view/index/index.php b/core/module/theme/view/index/index.php index 3a8877f6..0f7dc960 100755 --- a/core/module/theme/view/index/index.php +++ b/core/module/theme/view/index/index.php @@ -5,7 +5,7 @@ ): ?>
    -
    +
    'buttonGrey', 'href' => helper::baseUrl(false), @@ -13,21 +13,21 @@ 'value' => 'Accueil' ]); ?>
    -
    +
    helper::baseUrl() . $this->getUrl(0) . '/manage', 'ico' => 'download', 'value' => 'Gestion des thèmes' ]); ?>
    -
    +
    helper::baseUrl() . $this->getUrl(0) . '/advanced', 'value' => 'Mode avancé', 'ico' => 'code' ]); ?>
    -
    +
    'eye', 'value' => 'Zones cachées' @@ -37,7 +37,7 @@
    -
    +
    'buttonGrey', 'href' => helper::baseUrl(false), @@ -45,14 +45,14 @@ 'value' => 'Accueil' ]); ?>
    -
    +
    helper::baseUrl() . $this->getUrl(0) . '/manage', 'ico' => 'download', 'value' => 'Gestion des thèmes' ]); ?>
    -
    +
    helper::baseUrl() . $this->getUrl(0) . '/advanced', 'value' => 'Mode avancé', diff --git a/core/module/theme/view/site/site.php b/core/module/theme/view/site/site.php index bf1e9f0f..87ac015f 100755 --- a/core/module/theme/view/site/site.php +++ b/core/module/theme/view/site/site.php @@ -40,7 +40,7 @@
    -
    +
    'colorPicker', 'label' => 'Boutons', @@ -82,6 +82,15 @@ ]); ?>
    +
    +
    + 'Répartition des blocs :', + 'help' => 'Pour éditer le contenu des blocs, sélectionnez \'Édition des blocs\' dans la liste des pages.', + 'selected' => $this->getData(['theme', 'site', 'blocks']) + ]); ?> +
    +
    diff --git a/core/module/user/user.php b/core/module/user/user.php index a8559cfd..a35b479a 100755 --- a/core/module/user/user.php +++ b/core/module/user/user.php @@ -88,10 +88,13 @@ class user extends common { * Suppression */ public function delete() { + // + // $url prend l'adresse sans le token + $url = explode('&',$this->getUrl(2)); // Accès refusé if( // L'utilisateur n'existe pas - $this->getData(['user', $this->getUrl(2)]) === null + $this->getData(['user', $url[0]]) === null // Groupe insuffisant AND ($this->getUrl('group') < self::GROUP_MODERATOR) ) { @@ -100,8 +103,23 @@ class user extends common { 'access' => false ]); } + // Jeton incorrect + elseif(!isset($_GET['csrf'])) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'user', + 'notification' => 'Jeton invalide' + ]); + } + elseif ($_GET['csrf'] !== $_SESSION['csrf']) { + // Valeurs en sortie + $this->addOutput([ + 'redirect' => helper::baseUrl() . 'user', + 'notification' => 'Suppression non autorisée' + ]); + } // Bloque la suppression de son propre compte - elseif($this->getUser('id') === $this->getUrl(2)) { + elseif($this->getUser('id') === $url[0]) { // Valeurs en sortie $this->addOutput([ 'redirect' => helper::baseUrl() . 'user', @@ -110,7 +128,7 @@ class user extends common { } // Suppression else { - $this->deleteData(['user', $this->getUrl(2)]); + $this->deleteData(['user', $url[0]]); // Valeurs en sortie $this->addOutput([ 'redirect' => helper::baseUrl() . 'user', @@ -280,7 +298,7 @@ class user extends common { ]), template::button('userDelete' . $userId, [ 'class' => 'userDelete buttonRed', - 'href' => helper::baseUrl() . 'user/delete/' . $userId, + 'href' => helper::baseUrl() . 'user/delete/' . $userId. '&csrf=' . $_SESSION['csrf'], 'value' => template::ico('cancel') ]) ]; diff --git a/core/module/user/view/add/add.php b/core/module/user/view/add/add.php index fbb0415e..78616aa7 100755 --- a/core/module/user/view/add/add.php +++ b/core/module/user/view/add/add.php @@ -43,7 +43,7 @@
  • Accès aux pages privées membres
    • -
    • Accès aux pages privées membres et modérateurs
    • +
    • Accès aux pages privées membres et éditeurs
    • Ajout / Édition / Suppression de pages
    • Ajout / Édition / Suppression de fichiers
    diff --git a/core/module/user/view/edit/edit.php b/core/module/user/view/edit/edit.php index 53465073..9bff48a0 100755 --- a/core/module/user/view/edit/edit.php +++ b/core/module/user/view/edit/edit.php @@ -58,7 +58,7 @@
  • Accès aux pages privées membres
    • -
    • Accès aux pages privées membres et modérateurs
    • +
    • Accès aux pages privées membres et éditeurs
    • Ajout / Édition / Suppression de pages
    • Ajout / Édition / Suppression de fichiers
    diff --git a/core/vendor/filemanager/UploadHandler.php b/core/vendor/filemanager/UploadHandler.php index ed212191..780c54d3 100755 --- a/core/vendor/filemanager/UploadHandler.php +++ b/core/vendor/filemanager/UploadHandler.php @@ -380,6 +380,10 @@ class UploadHandler $file->error = $this->get_error_message('accept_file_types'); return false; } + if (preg_match($this->options['image_file_types'], $file->name) && function_exists('exif_imagetype') && !@exif_imagetype($uploaded_file)) { + $file->error = $this->get_error_message('accept_file_types'); + return false; + } if ($uploaded_file && is_uploaded_file($uploaded_file)) { $file_size = $this->get_file_size($uploaded_file); } else { @@ -519,7 +523,7 @@ class UploadHandler // Remove path information and dots around the filename, to prevent uploading // into different directories or replacing hidden system files. // Also remove control characters and spaces (\x00..\x20) around the filename: - $name = trim($this->basename(stripslashes($name)), ".\x00..\x20"); + $name = trim($this->basename(stripslashes($name)), "\x00..\x20"); // Use a timestamp for empty filenames: if (!$name) { $name = str_replace('.', '-', microtime(true)); @@ -1330,6 +1334,11 @@ class UploadHandler '', $content_disposition_header )) : null; + // TODO check + // if (isset($content_disposition_header) && !empty($content_disposition_header) ) { + // $file_name = str_replace('attachment; filename="', '', $content_disposition_header); + // $file_name = str_replace('"', '', $file_name); + // } // Parse the Content-Range header, which has the following form: // Content-Range: bytes 0-524287/2000000 $content_range_header = $this->get_server_var('HTTP_CONTENT_RANGE'); diff --git a/core/vendor/filemanager/ajax_calls.php b/core/vendor/filemanager/ajax_calls.php index 025d5cfe..0fe40f3f 100755 --- a/core/vendor/filemanager/ajax_calls.php +++ b/core/vendor/filemanager/ajax_calls.php @@ -1,8 +1,6 @@ send(); exit; } + + +//check $_GET['file'] +if(isset($_GET['file']) && !checkRelativePath($_GET['file'])) { + response(trans('wrong path').AddErrorLocation())->send(); + exit; +} + +//check $_POST['file'] +if(isset($_POST['path']) && !checkRelativePath($_POST['path'])) { + response(trans('wrong path').AddErrorLocation())->send(); + exit; +} + + $ftp = ftp_con($config); if(isset($_GET['action'])) @@ -52,7 +65,7 @@ if(isset($_GET['action'])) case 'filter': if (isset($_GET['type'])) { - if (isset($remember_text_filter) && $remember_text_filter) + if (isset($config['remember_text_filter']) && $config['remember_text_filter']) { $_SESSION['RF']["filter"] = $_GET['type']; } @@ -73,24 +86,10 @@ if(isset($_GET['action'])) $_SESSION['RF']["descending"] = $_GET['descending']; } break; - case 'image_size': // not used - $pos = strpos($_POST['path'], $upload_dir); - if ($pos !== false) - { - $info = getimagesize(substr_replace($_POST['path'], $current_path, $pos, strlen($upload_dir))); - response($info)->send(); - exit; - } - break; case 'save_img': $info = pathinfo($_POST['name']); - if ( - strpos($_POST['path'], '/') === 0 - || strpos($_POST['path'], '../') !== false - || strpos($_POST['path'], '..\\') !== false - || strpos($_POST['path'], './') === 0 - || (strpos($_POST['url'], 'http://s3.amazonaws.com/feather') !== 0 && strpos($_POST['url'], 'https://s3.amazonaws.com/feather') !== 0) + if ((strpos($_POST['url'], 'http://s3.amazonaws.com/feather') !== 0 && strpos($_POST['url'], 'https://s3.amazonaws.com/feather') !== 0) || $_POST['name'] != fix_filename($_POST['name'], $config) || ! in_array(strtolower($info['extension']), array( 'jpg', 'jpeg', 'png' )) ) @@ -106,7 +105,7 @@ if(isset($_GET['action'])) } if (!checkresultingsize(strlen($image_data))) { - response(sprintf(trans('max_size_reached'),$MaxSizeTotal).AddErrorLocation())->send(); + response(sprintf(trans('max_size_reached'),$config['MaxSizeTotal']).AddErrorLocation())->send(); exit; } if($ftp){ @@ -116,42 +115,36 @@ if(isset($_GET['action'])) $temp .=".".substr(strrchr($_POST['url'],'.'),1); file_put_contents($temp,$image_data); - $ftp->put($ftp_base_folder.$upload_dir . $_POST['path'] . $_POST['name'], $temp, FTP_BINARY); + $ftp->put($config['ftp_base_folder'].$config['upload_dir'] . $_POST['path'] . $_POST['name'], $temp, FTP_BINARY); create_img($temp,$temp,122,91); - $ftp->put($ftp_base_folder.$ftp_thumbs_dir. $_POST['path'] . $_POST['name'], $temp, FTP_BINARY); + $ftp->put($config['ftp_base_folder'].$config['ftp_thumbs_dir']. $_POST['path'] . $_POST['name'], $temp, FTP_BINARY); unlink($temp); }else{ - file_put_contents($current_path . $_POST['path'] . $_POST['name'],$image_data); - create_img($current_path . $_POST['path'] . $_POST['name'], $thumbs_base_path.$_POST['path'].$_POST['name'], 122, 91); + file_put_contents($config['current_path'] . $_POST['path'] . $_POST['name'],$image_data); + create_img($config['current_path'] . $_POST['path'] . $_POST['name'], $config['thumbs_base_path'].$_POST['path'].$_POST['name'], 122, 91); // TODO something with this function cause its blowing my mind new_thumbnails_creation( - $current_path.$_POST['path'], - $current_path.$_POST['path'].$_POST['name'], + $config['current_path'].$_POST['path'], + $config['current_path'].$_POST['path'].$_POST['name'], $_POST['name'], - $current_path, + $config['current_path'], $config ); } break; case 'extract': - if ( strpos($_POST['path'], '/') === 0 - || strpos($_POST['path'], '../') !== false - || strpos($_POST['path'], '..\\') !== false - || strpos($_POST['path'], './') === 0) - { - response(trans('wrong path'.AddErrorLocation()))->send(); - exit; + if(!$config['extract_files']){ + response(trans('wrong action').AddErrorLocation())->send(); } - if($ftp){ - $path = $ftp_base_url.$upload_dir . $_POST['path']; - $base_folder = $ftp_base_url.$upload_dir . fix_dirname($_POST['path']) . "/"; + $path = $config['ftp_base_url'].$config['upload_dir'] . $_POST['path']; + $base_folder = $config['ftp_base_url'].$config['upload_dir'] . fix_dirname($_POST['path']) . "/"; }else{ - $path = $current_path . $_POST['path']; - $base_folder = $current_path . fix_dirname($_POST['path']) . "/"; + $path = $config['current_path'] . $_POST['path']; + $base_folder = $config['current_path'] . fix_dirname($_POST['path']) . "/"; } $info = pathinfo($path); @@ -184,32 +177,28 @@ if(isset($_GET['action'])) $sizeTotalFinal += $aStat['size']; } if (!checkresultingsize($sizeTotalFinal)) { - response(sprintf(trans('max_size_reached'),$MaxSizeTotal).AddErrorLocation())->send(); + response(sprintf(trans('max_size_reached'),$config['MaxSizeTotal']).AddErrorLocation())->send(); exit; } - //make all the folders + //make all the folders and unzip into the folders for ($i = 0; $i < $zip->numFiles; $i++) { - $OnlyFileName = $zip->getNameIndex($i); - $FullFileName = $zip->statIndex($i); - if (substr($FullFileName['name'], -1, 1) == "/") - { - create_folder($base_folder . $FullFileName['name']); - } - } - //unzip into the folders - for ($i = 0; $i < $zip->numFiles; $i++) - { - $OnlyFileName = $zip->getNameIndex($i); $FullFileName = $zip->statIndex($i); - if ( ! (substr($FullFileName['name'], -1, 1) == "/")) - { - $fileinfo = pathinfo($OnlyFileName); - if (in_array(strtolower($fileinfo['extension']), $ext)) + if(checkRelativePath($FullFileName['name'])){ + if (substr($FullFileName['name'], -1, 1) == "/") { - copy('zip://' . $path . '#' . $OnlyFileName, $base_folder . $FullFileName['name']); + create_folder($base_folder . $FullFileName['name']); + } + + if ( ! (substr($FullFileName['name'], -1, 1) == "/")) + { + $fileinfo = pathinfo($FullFileName['name']); + if (in_array(strtolower($fileinfo['extension']), $config['ext'])) + { + copy('zip://' . $path . '#' . $FullFileName['name'], $base_folder . $FullFileName['name']); + } } } } @@ -234,7 +223,7 @@ if(isset($_GET['action'])) $phar = new PharData($path); $phar->decompressFiles(); $files = array(); - check_files_extensions_on_phar($phar, $files, '', $ext); + check_files_extensions_on_phar($phar, $files, '', $config); $phar->extractTo($base_folder, $files, true); break; @@ -246,22 +235,28 @@ if(isset($_GET['action'])) if($ftp){ unlink($path); - $ftp->putAll($base_folder, "/".$ftp_base_folder . $upload_dir . fix_dirname($_POST['path']), FTP_BINARY); + $ftp->putAll($base_folder, "/".$config['ftp_base_folder'] . $config['upload_dir'] . fix_dirname($_POST['path']), FTP_BINARY); deleteDir($base_folder); } break; case 'media_preview': + if(isset($_GET['file'])){ + $_GET['file'] = sanitize($_GET['file']); + } + if(isset($_GET['title'])){ + $_GET['title'] = sanitize($_GET['title']); + } if($ftp){ - $preview_file = $ftp_base_url.$upload_dir . $_GET['file']; + $preview_file = $config['ftp_base_url'].$config['upload_dir'] . $_GET['file']; }else{ - $preview_file = $current_path . $_GET["file"]; + $preview_file = $config['current_path'] . $_GET["file"]; } $info = pathinfo($preview_file); ob_start(); ?> - - +

    @@ -634,9 +633,9 @@ $class_ext = ''; $src = ''; if($ftp){ try{ - $files = $ftp->scanDir($ftp_base_folder.$upload_dir.$rfm_subfolder.$subdir); - if (!$ftp->isDir($ftp_base_folder.$ftp_thumbs_dir.$rfm_subfolder.$subdir)){ - create_folder(false,$ftp_base_folder.$ftp_thumbs_dir.$rfm_subfolder.$subdir,$ftp,$config); + $files = $ftp->scanDir($config['ftp_base_folder'].$config['upload_dir'].$rfm_subfolder.$subdir); + if (!$ftp->isDir($config['ftp_base_folder'].$config['ftp_thumbs_dir'].$rfm_subfolder.$subdir)){ + create_folder(false,$config['ftp_base_folder'].$config['ftp_thumbs_dir'].$rfm_subfolder.$subdir,$ftp,$config); } }catch(FtpClient\FtpException $e){ echo "Error: "; @@ -645,7 +644,7 @@ if($ftp){ die(); } }else{ - $files = scandir($current_path.$rfm_subfolder.$subdir); + $files = scandir($config['current_path'].$rfm_subfolder.$subdir); } $n_files= count($files); @@ -664,11 +663,14 @@ foreach($files as $k=>$file){ if($file['type']=='file'){ $current_files_number++; $file_ext = substr(strrchr($file['name'],'.'),1); + $is_dir = false; }else{ $current_folders_number++; $file_ext=trans('Type_dir'); + $is_dir = true; } $sorted[$k]=array( + 'is_dir'=>$is_dir, 'file'=>$file['name'], 'file_lcase'=>strtolower($file['name']), 'date'=>$date, @@ -680,16 +682,17 @@ foreach($files as $k=>$file){ if($file!="." && $file!=".."){ - if(is_dir($current_path.$rfm_subfolder.$subdir.$file)){ - $date=filemtime($current_path.$rfm_subfolder.$subdir. $file); + if(is_dir($config['current_path'].$rfm_subfolder.$subdir.$file)){ + $date=filemtime($config['current_path'].$rfm_subfolder.$subdir. $file); $current_folders_number++; - if($show_folder_size){ - list($size,$nfiles,$nfolders) = folder_info($current_path.$rfm_subfolder.$subdir.$file,false); + if($config['show_folder_size']){ + list($size,$nfiles,$nfolders) = folder_info($config['current_path'].$rfm_subfolder.$subdir.$file,false); } else { $size=0; } $file_ext=trans('Type_dir'); $sorted[$k]=array( + 'is_dir'=>true, 'file'=>$file, 'file_lcase'=>strtolower($file), 'date'=>$date, @@ -697,17 +700,18 @@ foreach($files as $k=>$file){ 'permissions' =>'', 'extension'=>fix_strtolower($file_ext) ); - if($show_folder_size){ + if($config['show_folder_size']){ $sorted[$k]['nfiles'] = $nfiles; $sorted[$k]['nfolders'] = $nfolders; } }else{ $current_files_number++; - $file_path=$current_path.$rfm_subfolder.$subdir.$file; + $file_path=$config['current_path'].$rfm_subfolder.$subdir.$file; $date=filemtime($file_path); $size=filesize($file_path); $file_ext = substr(strrchr($file,'.'),1); $sorted[$k]=array( + 'is_dir'=>false, 'file'=>$file, 'file_lcase'=>strtolower($file), 'date'=>$date, @@ -720,18 +724,52 @@ foreach($files as $k=>$file){ } } - function filenameSort($x, $y) { - return $x['file_lcase'] < $y['file_lcase']; + global $descending; + + if($x['is_dir'] !== $y['is_dir']){ + return $y['is_dir']; + } else { + return ($descending) + ? $x['file_lcase'] < $y['file_lcase'] + : $x['file_lcase'] >= $y['file_lcase']; + } } + function dateSort($x, $y) { - return $x['date'] < $y['date']; + global $descending; + + if($x['is_dir'] !== $y['is_dir']){ + return $y['is_dir']; + } else { + return ($descending) + ? $x['date'] < $y['date'] + : $x['date'] >= $y['date']; + } } + function sizeSort($x, $y) { - return $x['size'] < $y['size']; + global $descending; + + if($x['is_dir'] !== $y['is_dir']){ + return $y['is_dir']; + } else { + return ($descending) + ? $x['size'] < $y['size'] + : $x['size'] >= $y['size']; + } } + function extensionSort($x, $y) { - return $x['extension'] < $y['extension']; + global $descending; + + if($x['is_dir'] !== $y['is_dir']){ + return $y['is_dir']; + } else { + return ($descending) + ? $x['extension'] < $y['extension'] + : $x['extension'] >= $y['extension']; + } } switch($sort_by){ @@ -749,15 +787,12 @@ switch($sort_by){ break; } -if(!$descending){ - $sorted=array_reverse($sorted); -} - if($subdir!=""){ $sorted = array_merge(array(array('file'=>'..')),$sorted); } $files=$sorted; + ?>