Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue 884 #1150

Merged
merged 3 commits into from Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
24 changes: 21 additions & 3 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,13 +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;
$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 @@ -62,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 Down Expand Up @@ -93,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
16 changes: 7 additions & 9 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,15 +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
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 @@ -97,7 +91,7 @@ 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)
Expand All @@ -113,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',
'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
13 changes: 6 additions & 7 deletions tools/bazar/presentation/javascripts/image-field.js
Expand Up @@ -34,13 +34,12 @@ function handleFileSelect(evt) {
if (!f.type.match('image.*')) {
continue
}
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
1 change: 1 addition & 0 deletions tools/lang/yeswiki-extension-lang