Skip to content

Commit

Permalink
fix(bazar): fix issue 884 with grace and plentyness
Browse files Browse the repository at this point in the history
  • Loading branch information
12b authored and mrflos committed Apr 25, 2024
1 parent 9f7dcb3 commit 787db88
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 74 deletions.
3 changes: 2 additions & 1 deletion docs/fr/bazar.md
Expand Up @@ -163,14 +163,15 @@ Un champ de type image permet d'importer un fichier image qui sera ensuite visua
- **Hauteur re-dimension** : YesWiki peut harmoniser la taille des images importées pour ce formulaire. Ce paramètre permet de préciser la hauteur de cette image redimensionnée.
- **Largeur re-dimension** : YesWiki peut harmoniser la taille des images importées pour ce formulaire. Ce paramètre permet de préciser la largeur de cette image redimensionnée.
- **Alignement** : C'est là que l'on paramètre le comportement d'affichage de l'image. Son fonctionnement est similaire à ce qui se passe dans l'édition de pages (quand on joint une image avec le bouton Fichier).
- **Taille max** Ce paramètre permet de limiter la taille du fichier. Il s'agit d'un nombre d'octets mais qui peut être écrit avec des préfixe d'unités : k pour kilo, m pour mega (par ex.: 2097152, 2048k, 2m). Si la valeur donnée dépasse la valeur configurée sur le serveur, la valeur du serveur sera prise.

### URL
Permet de saisir un lien web qui sera cliquable dans la fiche

### Upload de fichier
Ce type de champ permet d'uploader un fichier (par exemple au format PDF). Ce fichier est ensuite téléchargeable par les personnes qui visualisent la fiche.
#### Paramètres spécifiques au type de champs « upload de fichier » :
- **Taille max** Ce paramètre permet de limiter la taille du fichier. Il s'agit d'un nombre d'octets (par ex. 2000000 équivalent à 2 Mo).
- **Taille max** Ce paramètre permet de limiter la taille du fichier. Il s'agit d'un nombre d'octets mais qui peut être écrit avec des préfixe d'unités : k pour kilo, m pour mega (par ex.: 2097152, 2048k, 2m). Si la valeur donnée dépasse la valeur configurée sur le serveur, la valeur du serveur sera prise.

### Email
Ce type de champs permet de saisir une adresse électronique. YesWiki effectue automatiquement des contrôles sur la syntaxe de l'adresse et propose également de paramétrer des comportements spécifiquement liés à ce type de données.
Expand Down
27 changes: 10 additions & 17 deletions includes/YesWiki.php
Expand Up @@ -1386,31 +1386,24 @@ public function parse_size($size)
$size = preg_replace('/[^0-9\.]/', '', $size); // Remove the non-numeric characters from the size.
if ($unit) {
// Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
return round($size * pow(1024, stripos('bkmgtpezy', $unit[0])));
return intval(round($size * pow(1024, stripos('bkmgtpezy', $unit[0]))));
} else {
return round($size);
return intval(round($size));
}
}

// Drupal code under GPL2 cf. http://stackoverflow.com/questions/13076480/php-get-actual-maximum-upload-size#25370978
// Returns a file size limit in bytes based on the PHP upload_max_filesize
// and post_max_size
// Returns a file size limit in bytes based on the PHP upload_max_filesize,
// post_max_size and wakka config max_file_size
public function file_upload_max_size()
{
static $max_size = -1;
$conf_max_file_size = $this->GetConfigValue("max_file_size") ? $this->parse_size($this->GetConfigValue("max_file_size")) : 0;

if ($max_size < 0) {
// Start with post_max_size.
$max_size = $this->parse_size(ini_get('post_max_size'));
$post_max_size = $this->parse_size(ini_get('post_max_size'));

// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = $this->parse_size(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = $upload_max;
}
}
return $max_size;
$upload_max = $this->parse_size(ini_get('upload_max_filesize'));

// return the min size limit, excluding 0 values that mean no limit
return min(array_filter([$conf_max_file_size, $post_max_size, $upload_max]) ?? DEFAULT_MAX_UPLOAD_SIZE);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions includes/constants.php
Expand Up @@ -55,3 +55,6 @@

// for package updates
define('SEMVER', '(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?');

// default max size for upload
define('DEFAULT_MAX_UPLOAD_SIZE', 2000*1024);
2 changes: 1 addition & 1 deletion tools/attach/lang/attach_fr.inc.php
Expand Up @@ -118,6 +118,6 @@
// edit config action
'EDIT_CONFIG_HINT_ATTACH-VIDEO-CONFIG[DEFAULT_VIDEO_SERVICE]' => 'Service de vidéo par défaut (peertube, youtube ou vimeo)',
'EDIT_CONFIG_HINT_ATTACH-VIDEO-CONFIG[DEFAULT_PEERTUBE_INSTANCE]' => 'Adresse du serveur peertube par défaut',
'EDIT_CONFIG_HINT_MAX_FILE_SIZE' => 'Taille maximum des fichiers téléversés - octets (ex: Taille maximum des fichiers téléversés - octets (ex: 2097152 pour 2Mo)',
'EDIT_CONFIG_HINT_MAX_FILE_SIZE' => 'Taille maximum des fichiers téléversés - octets (ex: Taille maximum des fichiers téléversés (ex: 2097152, 2048k, 2m)',
'EDIT_CONFIG_GROUP_ATTACH' => 'Insertion de médias (images, vidéos)',
];
24 changes: 1 addition & 23 deletions tools/attach/libs/attach.lib.php
Expand Up @@ -49,7 +49,7 @@ public function __construct(&$wiki)
}

if (empty($this->attachConfig['max_file_size'])) {
$this->attachConfig['max_file_size'] = $this->wiki->GetConfigValue("max_file_size") ? $this->wiki->GetConfigValue("max_file_size") : $this->file_upload_max_size();
$this->attachConfig['max_file_size'] = $this->params->get("max-upload-size");
}

$safemode = $this->wiki->GetConfigValue("no_safe_mode");
Expand All @@ -67,28 +67,6 @@ public function __construct(&$wiki)
/******************************************************************************
* FONCTIONS UTILES
*******************************************************************************/
// Returns a file size limit in bytes based on the PHP upload_max_filesize
// and post_max_size
public function file_upload_max_size()
{
static $max_size = -1;

if ($max_size < 0) {
// Start with post_max_size.
$post_max_size = $this->parse_size(ini_get('post_max_size'));
if ($post_max_size > 0) {
$max_size = $post_max_size;
}

// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = $this->parse_size(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = $upload_max;
}
}
return $max_size;
}
/**
* transforme des valeurs en mega / kilo / giga octets en entier
*
Expand Down
2 changes: 0 additions & 2 deletions tools/bazar/config.yaml
Expand Up @@ -41,8 +41,6 @@ parameters:
# Valeur par defaut d'etat de la fiche annonce apres saisie
# 0 pour 'en attente de validation', 1 pour 'directement validee'
BAZ_ETAT_VALIDATION: '1'
# Valeur maximale en octets pour la taille d'un fichier joint a telecharger
BAZ_TAILLE_MAX_FICHIER: '%max-upload-size%'
# Type d'affichage des dates dans la liste
# Mettre jma pour jour mois annee, ou jm, ou jmah
BAZ_TYPE_AFFICHAGE_LISTE: 'jma'
Expand Down
26 changes: 21 additions & 5 deletions tools/bazar/fields/FileField.php
Expand Up @@ -8,6 +8,7 @@
use YesWiki\Bazar\Service\EntryManager;
use YesWiki\Bazar\Service\Guard;
use YesWiki\Core\Service\EventDispatcher;
use YesWiki\Core\Service\AssetsManager;
use YesWiki\Security\Controller\SecurityController;

/**
Expand All @@ -16,10 +17,12 @@
class FileField extends BazarField
{
protected $readLabel;
protected const FIELD_MAX_SIZE = 14;
protected const FIELD_READ_LABEL = 6;
protected const FIELD_AUTHORIZED_EXTS_LABEL = 7;

protected $attach;
protected $maxSize;
protected $authorizedExts;

public function __construct(array $values, ContainerInterface $services)
Expand All @@ -37,14 +40,24 @@ public function __construct(array $values, ContainerInterface $services)
$this->authorizedExts = array_filter($exts, function ($ext) {
return preg_match('/^\.[a-z0-9]{1,4}+$/', $ext);
});
$maxFieldSize = $values[self::FIELD_MAX_SIZE] ?
$this->getWiki()->parse_size($values[self::FIELD_MAX_SIZE]) :
0;

// take the min size limit, excluding 0 values that mean no limit
$this->maxSize = min(array_filter(
[
$maxFieldSize,
$this->getService(ParameterBagInterface::class)->get('max-upload-size')]
));
}

protected function renderInput($entry)
{
$wiki = $this->getWiki();
$value = $this->getValue($entry);

$deletedFile = false;
// ToDo: Faire comme dans ImageField pour vérifier que la taille du fichier n'est pas trop grosse
$wiki->services->get(AssetsManager::class)->AddJavascriptFile('tools/bazar/presentation/javascripts/file-field.js');

if (!empty($value)) {
if (!empty($entry) && isset($_GET['delete_file']) && $_GET['delete_file'] === $value) {
Expand All @@ -63,10 +76,11 @@ protected function renderInput($entry)
}
}
}

return ($alertMessage ?? '') . $this->render('@bazar/inputs/file.twig', (
empty($value) || !file_exists($this->getBasePath(). $value) || $deletedFile
? []
? [
'maxSize' => $this->maxSize
]
: [
'value' => $value,
'shortFileName' => $this->getShortFileName($value),
Expand All @@ -79,7 +93,6 @@ protected function renderInput($entry)

public function formatValuesBeforeSave($entry)
{
// ToDo: Vérifier que le fichier à bien été téléchargé et que sa taille n'est pas trop grosse
$value = $this->getValue($entry);

$params = $this->getService(ParameterBagInterface::class);
Expand All @@ -95,6 +108,9 @@ public function formatValuesBeforeSave($entry)
$extension = preg_replace("/_$/", "", $extension);
if ($extension != '' && in_array($extension, array_keys($params->get('authorized-extensions')))) {
if (!file_exists($filePath)) {
if ($_FILES[$this->propertyName]['size'] > $this->maxSize) {
throw new \Exception(_t('BAZ_FILEFIELD_TOO_LARGE_FILE', ['fileMaxSize' => $this->maxSize]));
}
move_uploaded_file($_FILES[$this->propertyName]['tmp_name'], $filePath);
chmod($filePath, 0755);
} else {
Expand Down
18 changes: 7 additions & 11 deletions tools/bazar/fields/ImageField.php
Expand Up @@ -4,7 +4,7 @@

use Psr\Container\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use YesWiki\Core\Service\AclService;
use YesWiki\Core\Service\AssetsManager;
use YesWiki\Security\Controller\SecurityController;

/**
Expand Down Expand Up @@ -43,16 +43,9 @@ protected function renderInput($entry)
{
$wiki = $this->getWiki();
$value = $this->getValue($entry);
$maxSize = $wiki->config['BAZ_TAILLE_MAX_FICHIER'] ;

// javascript pour gerer la previsualisation

// si une taille maximale est indiquée, on teste
// ToDo: améliorer pour prendre la taille max définie au niveau du champ si elle existe et faire pareil dans FileField
if (!empty($maxSize)) {
$wiki->addJavascript("var imageMaxSize = {$maxSize};");
}
$wiki->AddJavascriptFile('tools/bazar/presentation/javascripts/image-field.js');
$wiki->services->get(AssetsManager::class)->AddJavascriptFile('tools/bazar/presentation/javascripts/image-field.js');

if (isset($value) && $value != '') {
if (isset($_GET['suppr_image']) && $_GET['suppr_image'] === $value) {
Expand Down Expand Up @@ -98,12 +91,11 @@ protected function renderInput($entry)
]);
}
}
return ($alertMessage ?? '') .$this->render('@bazar/inputs/image.twig');
return ($alertMessage ?? '') .$this->render('@bazar/inputs/image.twig', ['maxSize' => $this->maxSize]);
}

public function formatValuesBeforeSave($entry)
{
// ToDo: Vérifier que l'image à bien été téléchargée et que sa taille n'est pas trop grosse
$params = $this->getService(ParameterBagInterface::class);
$value = $this->getValue($entry);
if (!empty($_FILES[$this->propertyName]['name']) && !empty($entry['id_fiche'])) {
Expand All @@ -115,6 +107,10 @@ public function formatValuesBeforeSave($entry)

if ($this->isImage($rawFileName) && !$this->getService(SecurityController::class)->isWikiHibernated()) {
if (!file_exists($filePath)) {
if ($_FILES[$this->propertyName]['size'] > $this->maxSize) {
throw new \Exception(_t('BAZ_FILEFIELD_TOO_LARGE_FILE', ['fileMaxSize' => $this->maxSize]));
}

move_uploaded_file($_FILES[$this->propertyName]['tmp_name'], $filePath);
chmod($filePath, 0755);

Expand Down
1 change: 1 addition & 0 deletions tools/bazar/lang/bazar_fr.inc.php
Expand Up @@ -296,6 +296,7 @@
'BAZ_FILE_ALREADY_EXISTING' => 'fichier déja existant',
'BAZ_NOT_AUTHORIZED_FILE' => 'fichier non autorise',
'BAZ_FILEFIELD_FILE' => 'Fichier : {filename}',
'BAZ_FILEFIELD_TOO_LARGE_FILE' => 'Le fichier est trop volumineux, maximum %{fileMaxSize} octets',

// fields/ImageField.php
'BAZ_IMAGE_ALREADY_EXISTING' => 'L\'image {fileName} existait d&eacute;ja, elle n\'a pas &eacute;t&eacute; remplac&eacute;e.',
Expand Down
4 changes: 3 additions & 1 deletion tools/bazar/lang/bazarjs_fr.inc.php
Expand Up @@ -16,6 +16,8 @@
// fields/FileField.php
'BAZ_FILEFIELD_FILE' => 'Fichier : {filename}',
'BAZ_FORM_EDIT_FILE_READLABEL_LABEL' => 'Label à l\'affichage',
'FILEFIELD_TOO_LARGE_FILE' => 'Le fichier est trop volumineux, maximum {fileMaxSize} octets',


// fields/ImageField.php
'IMAGEFIELD_TOO_LARGE_IMAGE' => 'L\'image est trop volumineuse, maximum {imageMaxSize} octets',
Expand Down Expand Up @@ -203,7 +205,7 @@
'BAZ_FORM_EDIT_TEXTAREA_SIZE_LABEL' => 'Largeur champ de saisie',
'BAZ_FORM_EDIT_TEXTAREA_ROWS_LABEL' => 'Nombre de lignes',
'BAZ_FORM_EDIT_TEXTAREA_ROWS_PLACEHOLDER' => 'Défaut vide = 3 lignes',
'BAZ_FORM_EDIT_FILE_MAXSIZE_LABEL' => 'Taille max (en octets)',
'BAZ_FORM_EDIT_FILE_MAXSIZE_LABEL' => 'Taille max (ex: 2097152, 2048k, 2m)',
'BAZ_FORM_EDIT_INSCRIPTIONLISTE_EMAIL_LABEL' => 'Email pour s\'inscrire',
'BAZ_FORM_EDIT_INSCRIPTIONLISTE_EMAIL_FIELDID' => 'Champ du formulaire fournissant l\'email à inscire',
'BAZ_FORM_EDIT_INSCRIPTIONLISTE_MAILINGLIST' => 'Type de service de diffusion',
Expand Down
20 changes: 20 additions & 0 deletions tools/bazar/presentation/javascripts/file-field.js
@@ -0,0 +1,20 @@
function handleFileSelect(evt) {
const target = evt.target || evt.srcElement
const { id } = target
const { files } = target // FileList object

for (var i = 0, f; f = files[i]; i++) {
let fileMaxSize = document.getElementById(id).dataset.maxSize
if (f.size > fileMaxSize) {
alert(_t('FILEFIELD_TOO_LARGE_FILE', { fileMaxSize }))
document.getElementById(id).type = ''
document.getElementById(id).type = 'file'
continue
}
}
}

const fileinputs = document.getElementsByClassName('yw-file-upload')
for (let i = 0; i < fileinputs.length; i++) {
fileinputs.item(i).addEventListener('change', handleFileSelect, false)
}
Expand Up @@ -21,7 +21,7 @@ export default {
},
advancedAttributes: ['read', 'write', 'semantic', 'maxsize','authorizedExts'],
// disabledAttributes: [],
attributesMapping: { ...defaultMapping, ...{ 3: 'maxsize', 6: 'readlabel', 7: 'authorizedExts' } },
attributesMapping: { ...defaultMapping, ...{ 14: 'maxsize', 6: 'readlabel', 7: 'authorizedExts' } },
// renderInput(field) {
// return {
// field: `<input type="file"/>`,
Expand Down
Expand Up @@ -19,11 +19,12 @@ export default {
value: 'right',
options: { left: _t('LEFT'), right: _t('RIGHT') }
},
maxsize: { label: _t('BAZ_FORM_EDIT_FILE_MAXSIZE_LABEL'), value: '' },
read: readConf,
write: writeconf,
semantic: semanticConf
},
advancedAttributes: ['read', 'write', 'semantic', 'thumb_height','thumb_width','resize_height','resize_width'],
advancedAttributes: ['read', 'write', 'semantic', 'thumb_height','thumb_width','resize_height','resize_width','maxsize'],
// disabledAttributes: [],
attributesMapping: {
...defaultMapping,
Expand All @@ -33,7 +34,8 @@ export default {
4: 'thumb_width',
5: 'resize_height',
6: 'resize_width',
7: 'align'
7: 'align',
14: 'maxsize'
}
},
renderInput(fieldData) {
Expand Down
14 changes: 6 additions & 8 deletions tools/bazar/presentation/javascripts/image-field.js
Expand Up @@ -34,14 +34,12 @@ function handleFileSelect(evt) {
if (!f.type.match('image.*')) {
continue
}
// ToDo: Faire pareil pour file-field
if (typeof imageMaxSize !== 'undefined') {
if (f.size > imageMaxSize) {
alert(_t('IMAGEFIELD_TOO_LARGE_IMAGE', { imageMaxSize }))
document.getElementById(id).type = ''
document.getElementById(id).type = 'file'
continue
}
let imageMaxSize = document.getElementById(id).dataset.maxSize
if (f.size > imageMaxSize) {
alert(_t('IMAGEFIELD_TOO_LARGE_IMAGE', { imageMaxSize }))
document.getElementById(id).type = ''
document.getElementById(id).type = 'file'
continue
}
const reader = new FileReader()
// Closure to capture the file information.
Expand Down
3 changes: 2 additions & 1 deletion tools/bazar/templates/inputs/file.twig
Expand Up @@ -33,10 +33,11 @@
{% block inputblock %}
<input
type="file"
data-max-size="{{ maxSize }}"
id="{{ field.propertyName }}"
name="{{ field.propertyName }}"
{% if style %}style="{{ style }}"{% endif %}
class="form-control"
class="form-control yw-file-upload"
{% if field.authorizedExts is not empty %}accept="{{field.authorizedExts|join(',')}}"{% endif %}
{% if field.required %}required{% endif %}
/>
Expand Down
3 changes: 2 additions & 1 deletion tools/bazar/templates/inputs/image.twig
Expand Up @@ -34,11 +34,12 @@
<input type="hidden" id="oldimage_{{ field.propertyName }}" name="oldimage_{{ field.propertyName }}" value="{{ value }}" />
{% else %}
<input
data-max-size="{{ maxSize}}"
type="file"
class="yw-image-upload form-control"
id="{{ field.propertyName }}"
name="{{ field.propertyName }}"
accept=".jpeg, .jpg, .gif, .png"
accept=".webp, .jpeg, .jpg, .gif, .png"
{% if field.required %}required{% endif %}
>
<output id="img-{{ field.propertyName }}" class="col-xs-9"></output>
Expand Down

0 comments on commit 787db88

Please sign in to comment.