Browse Source

Merge branch '114_dev'

master
Fred Tempez 3 months ago
parent
commit
188dd6b17d
  1. 19
      .gitignore
  2. 2
      .htaccess
  3. 29
      CHANGES.md
  4. 2
      README.md
  5. 18
      core/class/helper.class.php
  6. 10
      core/class/jsondb/JsonDb.class.php
  7. 5
      core/class/phpmailer/Exception.class.php
  8. 812
      core/class/phpmailer/PHPMailer.class.php
  9. 235
      core/class/phpmailer/SMTP.class.php
  10. 38
      core/class/phpmailer/phpmailer.lang-fr.php
  11. 28
      core/class/template.class.php
  12. 11
      core/core.js.php
  13. 302
      core/core.php
  14. 164
      core/include/update.inc.php
  15. 3
      core/layout/blank.php
  16. 13
      core/layout/main.php
  17. 6
      core/module/addon/addon.php
  18. 8
      core/module/addon/view/index/index.help.html
  19. 8
      core/module/addon/view/index/index.php
  20. 2
      core/module/addon/view/store/store.php
  21. 104
      core/module/config/config.php
  22. 49
      core/module/config/view/connect/connect.php
  23. 12
      core/module/config/view/locale/locale.php
  24. 42
      core/module/config/view/restore/restore.php
  25. 5
      core/module/config/view/setup/setup.php
  26. 2
      core/module/config/view/social/social.php
  27. 55
      core/module/install/install.php
  28. 125
      core/module/install/ressource/defaultdata.php
  29. 42
      core/module/page/page.php
  30. 6
      core/module/page/view/edit/edit.js.php
  31. 8
      core/module/sitemap/sitemap.php
  32. 2308
      core/module/theme/theme.php
  33. 8
      core/module/theme/view/admin/admin.php
  34. 9
      core/module/theme/view/fontAdd/fontAdd.js.php
  35. 44
      core/module/theme/view/fontAdd/fontAdd.php
  36. 18
      core/module/theme/view/fontEdit/fontEdit.css
  37. 59
      core/module/theme/view/fontEdit/fontEdit.js.php
  38. 85
      core/module/theme/view/fontEdit/fontEdit.php
  39. 16
      core/module/theme/view/fonts/fonts.php
  40. 10
      core/module/theme/view/footer/footer.php
  41. 13
      core/module/theme/view/header/header.js.php
  42. 42
      core/module/theme/view/header/header.php
  43. 4
      core/module/theme/view/index/index.php
  44. 6
      core/module/theme/view/menu/menu.php
  45. 11
      core/module/theme/view/site/site.js.php
  46. 16
      core/module/theme/view/site/site.php
  47. 4
      core/module/user/user.php
  48. 4
      core/vendor/filemanager/config/config.php
  49. 4
      core/vendor/tinymce/init.js
  50. 20
      module/blog/blog.php
  51. 4
      module/blog/view/edit/edit.php
  52. 2
      module/form/form.php
  53. 2
      module/form/view/config/config.js.php
  54. 153
      module/gallery/gallery.php
  55. 22
      module/gallery/vendor/tablednd/MIT-LICENSE.txt
  56. 3
      module/gallery/vendor/tablednd/lisez-moi.txt
  57. 4
      module/gallery/vendor/tablednd/tablednd.min.js
  58. 19
      module/gallery/view/add/add.css
  59. 87
      module/gallery/view/add/add.js.php
  60. 68
      module/gallery/view/add/add.php
  61. 67
      module/gallery/view/config/config.js.php
  62. 83
      module/gallery/view/config/config.php
  63. 18
      module/gallery/view/edit/edit.js.php
  64. 101
      module/gallery/view/edit/edit.php
  65. 4
      module/gallery/view/gallery/gallery.js.php
  66. 26
      module/gallery/view/gallery/gallery.php
  67. 39
      module/gallery/view/option/option.php
  68. 18
      module/gallery/view/option/options.css
  69. 229
      module/gallery/view/theme/theme.php
  70. 14
      module/news/news.php

19
.gitignore vendored

@ -1,19 +0,0 @@
# Fichiers du site
site/*
# Dossiers vides dans GitHub
!.gitkeep
/.git
# PHPStorm
.idea/
# Trucs
core/vendor/tinymce/link_list.json
.vscode/*
sitemap.xml.gz
sitemap.xml
robots.txt
.DS_Store
# Service de mise à jour
gitupdate.sh

2
.htaccess

@ -32,5 +32,5 @@ Options -Indexes
Options -MultiViews
</IfModule>
# Attention, surtout ne rien modifier ci-dessous !
# ne pas supprimer la ligne URL rewriting !
# URL rewriting

29
CHANGES.md

@ -1,5 +1,33 @@
# Changelog
## Version 11.4.00
### Nouveautés :
- Compatibilité avec PHP 8.1
- Prise en charge des fontes Web Safe. Les fontes initiales sont transférées dans les fontes optionnelles, donc effaçables.
- Toutes les fontes en ligne sont désormais acceptées quel que soit le CDN, Google Fonte (avec preconnect), CDN Fontes ou autres.
- Désormais, les URL internes sont relatives, cela signifie qu'elles ne contiendront plus le domaine et le chemin d'accès au site. Cela permettra le déplacement d'un site d'un hébergement à un autre, d'un dossier d'hébergement à un autre, sans avoir à convertir les adresses internes. Les données d'un site mis à jour et importées d'une version antérieures sont automatiquement converties. En conséquence, le bloc de conversion de la fenêtre d'import est supprimé.
- Suppression temporaire de l'option d'installation d'un module, il faudra passer par une connexion FTP pour cela. Cette fonctionnalité a été réécrite pour la version 11.2.
### Améliorations :
- Configuration de la bannière, modalité d'affichage de la taille d'image recommandée et affichage des dimensions de l'image.
- Edition d'une page, le nom court se complète automatiquement.
- Configuration de la connexion, une option autorise l'affichage de la page de connexion lorsqu'une page de gestion du site est demandée: 'user', 'theme', 'config', 'edit', 'translate', 'addon'.
- L'option de réécriture d'URL n'est pas plus active avec le serveur Nginx.
- Galerie, version 3.5 :
- Nouvelle structure anticipée sur la version 12, le formulaire d'ajout de la galerie est séparé de la liste des galeries du module.
- Lorsque la galerie n'en contient qu'**une seule galerie**, elle peut être affichée directement, la liste des galeries étant ignorée. Pour cela, activer cette option dans les options de la galerie.
- Le contenu de la page peut désormais être affiché avec le contenu de la galerie sélectionnée. Ce paramètre ce gère au niveau de chaque galerie.
- Déplacement du bouton de retour à la liste des galeries en bas de l'écran.
### Corrections :
- URL Rewrite Apache, bug d'interprétation d'activation de la réécriture d'URL lorsque des données ont été inscrites après la ligne servant de délimiteur *# URL rewriting* dans le fichier htaccess.
- Module Galerie : correction de bugs, tri des images, erreurs d'affectation.
- Module Blog : taille recommandée de l'image erronée lorsque la largeur de l'écran est réglée sur fluide (100%).
- Gestion des pages : positionnement dans le menu accessoire ou dans le menu standard.
- Safari sur Mac, bug avec les cookies qui ne sont pas stockés.
- Nettoyage du code.
### Mise à jour :
- TableDND, script JQUERY de tri de tables utilisé par la galerie passe en version 1.0.5
- PHPMailer 6.6.0
## Version 11.3.07
### Correction :
- Module galerie, option plein écran inopérante.
@ -16,7 +44,6 @@
- Sauvegarde des fontes avec le thème.
- Une fonte Websafe remplace une fonte locale dont le fichier n'est pas disponible.
## Version 11.3.05
### Correction :
- Dossier du fichier de fontes non créé empêchant la création du fichier des appels de fontes.

2
README.md

@ -1,4 +1,4 @@
# ZwiiCMS 11.3.07
# ZwiiCMS 11.4.00
Zwii est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation.

18
core/class/helper.class.php

@ -86,7 +86,7 @@ class helper {
* @param string $sort Type de tri à appliquer au tableau (SORT_ASC, SORT_DESC, ou null)
* @return array
*/
public static function arrayCollumn($array, $column, $sort = null) {
public static function arrayColumn($array, $column, $sort = null) {
$newArray = [];
if(empty($array) === false) {
$newArray = array_map(function($element) use($column) {
@ -104,6 +104,14 @@ class helper {
return $newArray;
}
/**
* Compatibilité avec les anciens modules
*/
public static function arrayCollumn($array, $column, $sort = null) {
return (helper::arrayColumn($array, $column, $sort));
}
/**
* Génère un backup des données de site
@ -255,11 +263,15 @@ class helper {
* @return bool
*/
public static function checkRewrite() {
if(self::$rewriteStatus === null) {
// N'interroge que le serveur Apache
if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) {
self::$rewriteStatus === false;
} elseif(self::$rewriteStatus === null) {
// Ouvre et scinde le fichier .htaccess
$htaccess = explode('# URL rewriting', file_get_contents('.htaccess'));
// Retourne un boolean en fonction du contenu de la partie réservée à l'URL rewriting
self::$rewriteStatus = (empty($htaccess[1]) === false);
//self::$rewriteStatus = (empty($htaccess[1]) === false);
self::$rewriteStatus = (strpos($htaccess[1], 'RewriteEngine on') > 0) ? true : false;
}
return self::$rewriteStatus;
}

10
core/class/jsondb/JsonDb.class.php

@ -31,6 +31,16 @@ class JsonDb extends \Prowebcraft\Dot
parent::__construct();
}
/**
* Reload data from file
* @return $this
*/
public function reload()
{
$this->loadData(true);
return $this;
}
/**
* Set value or array of values to path
*

5
core/class/phpmailer/Exception.class.php

@ -1,4 +1,5 @@
<?php
/**
* PHPMailer Exception class.
* PHP Version 5.5.
@ -9,7 +10,7 @@
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2017 Marcus Bointon
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
@ -34,6 +35,6 @@ class Exception extends \Exception
*/
public function errorMessage()
{
return '<strong>' . htmlspecialchars($this->getMessage()) . "</strong><br />\n";
return '<strong>' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "</strong><br />\n";
}
}

812
core/class/phpmailer/PHPMailer.class.php

File diff suppressed because it is too large Load Diff

235
core/class/phpmailer/SMTP.class.php

@ -1,4 +1,5 @@
<?php
/**
* PHPMailer RFC821 SMTP email transport class.
* PHP Version 5.5.
@ -9,7 +10,7 @@
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2019 Marcus Bointon
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
@ -34,7 +35,7 @@ class SMTP
*
* @var string
*/
const VERSION = '6.1.5';
const VERSION = '6.6.0';
/**
* SMTP line break constant.
@ -185,6 +186,8 @@ class SMTP
'Amazon_SES' => '/[\d]{3} Ok (.*)/',
'SendGrid' => '/[\d]{3} Ok: queued as (.*)/',
'CampaignMonitor' => '/[\d]{3} 2.0.0 OK:([a-zA-Z\d]{48})/',
'Haraka' => '/[\d]{3} Message Queued \((.*)\)/',
'Mailjet' => '/[\d]{3} OK queued as (.*)/',
];
/**
@ -311,17 +314,11 @@ class SMTP
*/
public function connect($host, $port = null, $timeout = 30, $options = [])
{
static $streamok;
//This is enabled by default since 5.0.0 but some providers disable it
//Check this once and cache the result
if (null === $streamok) {
$streamok = function_exists('stream_socket_client');
}
// Clear errors to avoid confusion
//Clear errors to avoid confusion
$this->setError('');
// Make sure we are __not__ connected
//Make sure we are __not__ connected
if ($this->connected()) {
// Already connected, generate error
//Already connected, generate error
$this->setError('Already connected to a server');
return false;
@ -329,18 +326,66 @@ class SMTP
if (empty($port)) {
$port = self::DEFAULT_PORT;
}
// Connect to the SMTP server
//Connect to the SMTP server
$this->edebug(
"Connection: opening to $host:$port, timeout=$timeout, options=" .
(count($options) > 0 ? var_export($options, true) : 'array()'),
self::DEBUG_CONNECTION
);
$this->smtp_conn = $this->getSMTPConnection($host, $port, $timeout, $options);
if ($this->smtp_conn === false) {
//Error info already set inside `getSMTPConnection()`
return false;
}
$this->edebug('Connection: opened', self::DEBUG_CONNECTION);
//Get any announcement
$this->last_reply = $this->get_lines();
$this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
$responseCode = (int)substr($this->last_reply, 0, 3);
if ($responseCode === 220) {
return true;
}
//Anything other than a 220 response means something went wrong
//RFC 5321 says the server will wait for us to send a QUIT in response to a 554 error
//https://tools.ietf.org/html/rfc5321#section-3.1
if ($responseCode === 554) {
$this->quit();
}
//This will handle 421 responses which may not wait for a QUIT (e.g. if the server is being shut down)
$this->edebug('Connection: closing due to error', self::DEBUG_CONNECTION);
$this->close();
return false;
}
/**
* Create connection to the SMTP server.
*
* @param string $host SMTP server IP or host name
* @param int $port The port number to connect to
* @param int $timeout How long to wait for the connection to open
* @param array $options An array of options for stream_context_create()
*
* @return false|resource
*/
protected function getSMTPConnection($host, $port = null, $timeout = 30, $options = [])
{
static $streamok;
//This is enabled by default since 5.0.0 but some providers disable it
//Check this once and cache the result
if (null === $streamok) {
$streamok = function_exists('stream_socket_client');
}
$errno = 0;
$errstr = '';
if ($streamok) {
$socket_context = stream_context_create($options);
set_error_handler([$this, 'errorHandler']);
$this->smtp_conn = stream_socket_client(
$connection = stream_socket_client(
$host . ':' . $port,
$errno,
$errstr,
@ -348,7 +393,6 @@ class SMTP
STREAM_CLIENT_CONNECT,
$socket_context
);
restore_error_handler();
} else {
//Fall back to fsockopen which should work in more places, but is missing some features
$this->edebug(
@ -356,17 +400,18 @@ class SMTP
self::DEBUG_CONNECTION
);
set_error_handler([$this, 'errorHandler']);
$this->smtp_conn = fsockopen(
$connection = fsockopen(
$host,
$port,
$errno,
$errstr,
$timeout
);
restore_error_handler();
}
// Verify we connected properly
if (!is_resource($this->smtp_conn)) {
restore_error_handler();
//Verify we connected properly
if (!is_resource($connection)) {
$this->setError(
'Failed to connect to server',
'',
@ -381,22 +426,19 @@ class SMTP
return false;
}
$this->edebug('Connection: opened', self::DEBUG_CONNECTION);
// SMTP server can take longer to respond, give longer timeout for first read
// Windows does not have support for this timeout function
//SMTP server can take longer to respond, give longer timeout for first read
//Windows does not have support for this timeout function
if (strpos(PHP_OS, 'WIN') !== 0) {
$max = (int) ini_get('max_execution_time');
// Don't bother if unlimited
if (0 !== $max && $timeout > $max) {
$max = (int)ini_get('max_execution_time');
//Don't bother if unlimited, or if set_time_limit is disabled
if (0 !== $max && $timeout > $max && strpos(ini_get('disable_functions'), 'set_time_limit') === false) {
@set_time_limit($timeout);
}
stream_set_timeout($this->smtp_conn, $timeout, 0);
stream_set_timeout($connection, $timeout, 0);
}
// Get any announcement
$announce = $this->get_lines();
$this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER);
return true;
return $connection;
}
/**
@ -420,7 +462,7 @@ class SMTP
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}
// Begin encrypted connection
//Begin encrypted connection
set_error_handler([$this, 'errorHandler']);
$crypto_ok = stream_socket_enable_crypto(
$this->smtp_conn,
@ -441,7 +483,7 @@ class SMTP
* @param string $username The user name
* @param string $password The password
* @param string $authtype The auth type (CRAM-MD5, PLAIN, LOGIN, XOAUTH2)
* @param OAuth $OAuth An optional OAuth instance for XOAUTH2 authentication
* @param OAuthTokenProvider $OAuth An optional OAuthTokenProvider instance for XOAUTH2 authentication
*
* @return bool True if successfully authenticated
*/
@ -458,11 +500,11 @@ class SMTP
}
if (array_key_exists('EHLO', $this->server_caps)) {
// SMTP extensions are available; try to find a proper authentication method
//SMTP extensions are available; try to find a proper authentication method
if (!array_key_exists('AUTH', $this->server_caps)) {
$this->setError('Authentication is not allowed at this stage');
// 'at this stage' means that auth may be allowed after the stage changes
// e.g. after STARTTLS
//'at this stage' means that auth may be allowed after the stage changes
//e.g. after STARTTLS
return false;
}
@ -506,22 +548,25 @@ class SMTP
}
switch ($authtype) {
case 'PLAIN':
// Start authentication
//Start authentication
if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
return false;
}
// Send encoded username and password
if (!$this->sendCommand(
'User & Password',
base64_encode("\0" . $username . "\0" . $password),
235
)
//Send encoded username and password
if (
//Format from https://tools.ietf.org/html/rfc4616#section-2
//We skip the first field (it's forgery), so the string starts with a null byte
!$this->sendCommand(
'User & Password',
base64_encode("\0" . $username . "\0" . $password),
235
)
) {
return false;
}
break;
case 'LOGIN':
// Start authentication
//Start authentication
if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
return false;
}
@ -533,17 +578,17 @@ class SMTP
}
break;
case 'CRAM-MD5':
// Start authentication
//Start authentication
if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
return false;
}
// Get the challenge
//Get the challenge
$challenge = base64_decode(substr($this->last_reply, 4));
// Build the response
//Build the response
$response = $username . ' ' . $this->hmac($challenge, $password);
// send encoded credentials
//send encoded credentials
return $this->sendCommand('Username', base64_encode($response), 235);
case 'XOAUTH2':
//The OAuth instance must be set up prior to requesting auth.
@ -552,7 +597,7 @@ class SMTP
}
$oauth = $OAuth->getOauth64();
// Start authentication
//Start authentication
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
return false;
}
@ -582,15 +627,15 @@ class SMTP
return hash_hmac('md5', $data, $key);
}
// The following borrowed from
// http://php.net/manual/en/function.mhash.php#27225
//The following borrowed from
//http://php.net/manual/en/function.mhash.php#27225
// RFC 2104 HMAC implementation for php.
// Creates an md5 HMAC.
// Eliminates the need to install mhash to compute a HMAC
// by Lance Rushing
//RFC 2104 HMAC implementation for php.
//Creates an md5 HMAC.
//Eliminates the need to install mhash to compute a HMAC
//by Lance Rushing
$bytelen = 64; // byte length for md5
$bytelen = 64; //byte length for md5
if (strlen($key) > $bytelen) {
$key = pack('H*', md5($key));
}
@ -613,7 +658,7 @@ class SMTP
if (is_resource($this->smtp_conn)) {
$sock_status = stream_get_meta_data($this->smtp_conn);
if ($sock_status['eof']) {
// The socket is valid but we are not connected
//The socket is valid but we are not connected
$this->edebug(
'SMTP NOTICE: EOF caught while checking if connected',
self::DEBUG_CLIENT
@ -623,7 +668,7 @@ class SMTP
return false;
}
return true; // everything looks good
return true; //everything looks good
}
return false;
@ -641,7 +686,7 @@ class SMTP
$this->server_caps = null;
$this->helo_rply = null;
if (is_resource($this->smtp_conn)) {
// close the connection and cleanup
//Close the connection and cleanup
fclose($this->smtp_conn);
$this->smtp_conn = null; //Makes for cleaner serialization
$this->edebug('Connection: closed', self::DEBUG_CONNECTION);
@ -651,7 +696,7 @@ class SMTP
/**
* Send an SMTP DATA command.
* Issues a data command and sends the msg_data to the server,
* finializing the mail transaction. $msg_data is the message
* finalizing the mail transaction. $msg_data is the message
* that is to be send with the headers. Each header needs to be
* on a single line followed by a <CRLF> with the message headers
* and the message body being separated by an additional <CRLF>.
@ -676,7 +721,7 @@ class SMTP
* NOTE: this does not count towards line-length limit.
*/
// Normalize line breaks before exploding
//Normalize line breaks before exploding
$lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data));
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
@ -722,7 +767,8 @@ class SMTP
//Send the lines to the server
foreach ($lines_out as $line_out) {
//RFC2821 section 4.5.2
//Dot-stuffing as per RFC5321 section 4.5.2
//https://tools.ietf.org/html/rfc5321#section-4.5.2
if (!empty($line_out) && $line_out[0] === '.') {
$line_out = '.' . $line_out;
}
@ -756,7 +802,16 @@ class SMTP
public function hello($host = '')
{
//Try extended hello first (RFC 2821)
return $this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host);
if ($this->sendHello('EHLO', $host)) {
return true;
}
//Some servers shut down the SMTP service here (RFC 5321)
if (substr($this->helo_rply, 0, 3) == '421') {
return false;
}
return $this->sendHello('HELO', $host);
}
/**
@ -946,12 +1001,12 @@ class SMTP
$this->client_send($commandstring . static::LE, $command);
$this->last_reply = $this->get_lines();
// Fetch SMTP code and possible error code explanation
//Fetch SMTP code and possible error code explanation
$matches = [];
if (preg_match('/^([\d]{3})[ -](?:([\d]\\.[\d]\\.[\d]{1,2}) )?/', $this->last_reply, $matches)) {
$code = (int) $matches[1];
$code_ex = (count($matches) > 2 ? $matches[2] : null);
// Cut off error code from each response line
//Cut off error code from each response line
$detail = preg_replace(
"/{$code}[ -]" .
($code_ex ? str_replace('.', '\\.', $code_ex) . ' ' : '') . '/m',
@ -959,7 +1014,7 @@ class SMTP
$this->last_reply
);
} else {
// Fall back to simple parsing if regex fails
//Fall back to simple parsing if regex fails
$code = (int) substr($this->last_reply, 0, 3);
$code_ex = null;
$detail = substr($this->last_reply, 4);
@ -1058,8 +1113,10 @@ class SMTP
{
//If SMTP transcripts are left enabled, or debug output is posted online
//it can leak credentials, so hide credentials in all but lowest level
if (self::DEBUG_LOWLEVEL > $this->do_debug &&
in_array($command, ['User & Password', 'Username', 'Password'], true)) {
if (
self::DEBUG_LOWLEVEL > $this->do_debug &&
in_array($command, ['User & Password', 'Username', 'Password'], true)
) {
$this->edebug('CLIENT -> SERVER: [credentials hidden]', self::DEBUG_CLIENT);
} else {
$this->edebug('CLIENT -> SERVER: ' . $data, self::DEBUG_CLIENT);
@ -1113,7 +1170,7 @@ class SMTP
if (!$this->server_caps) {
$this->setError('No HELO/EHLO was sent');
return;
return null;
}
if (!array_key_exists($name, $this->server_caps)) {
@ -1125,7 +1182,7 @@ class SMTP
}
$this->setError('HELO handshake was used; No information about server extensions available');
return;
return null;
}
return $this->server_caps[$name];
@ -1152,7 +1209,7 @@ class SMTP
*/
protected function get_lines()
{
// If the connection is bad, give up straight away
//If the connection is bad, give up straight away
if (!is_resource($this->smtp_conn)) {
return '';
}
@ -1166,24 +1223,52 @@ class SMTP
$selW = null;
while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
//Must pass vars in here as params are by reference
if (!stream_select($selR, $selW, $selW, $this->Timelimit)) {
//solution for signals inspired by https://github.com/symfony/symfony/pull/6540
set_error_handler([$this, 'errorHandler']);
$n = stream_select($selR, $selW, $selW, $this->Timelimit);
restore_error_handler();
if ($n === false) {
$message = $this->getError()['detail'];
$this->edebug(
'SMTP -> get_lines(): select failed (' . $message . ')',
self::DEBUG_LOWLEVEL
);
//stream_select returns false when the `select` system call is interrupted
//by an incoming signal, try the select again
if (stripos($message, 'interrupted system call') !== false) {
$this->edebug(
'SMTP -> get_lines(): retrying stream_select',
self::DEBUG_LOWLEVEL
);
$this->setError('');
continue;
}
break;
}
if (!$n) {
$this->edebug(
'SMTP -> get_lines(): select timed-out in (' . $this->Timelimit . ' sec)',
self::DEBUG_LOWLEVEL
);
break;
}
//Deliberate noise suppression - errors are handled afterwards
$str = @fgets($this->smtp_conn, self::MAX_REPLY_LENGTH);
$this->edebug('SMTP INBOUND: "' . trim($str) . '"', self::DEBUG_LOWLEVEL);
$data .= $str;
// If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
// or 4th character is a space or a line break char, we are done reading, break the loop.
// String array access is a significant micro-optimisation over strlen
//If response is only 3 chars (not valid, but RFC5321 S4.2 says it must be handled),
//or 4th character is a space or a line break char, we are done reading, break the loop.
//String array access is a significant micro-optimisation over strlen
if (!isset($str[3]) || $str[3] === ' ' || $str[3] === "\r" || $str[3] === "\n") {
break;
}
// Timed-out? Log and break
//Timed-out? Log and break
$info = stream_get_meta_data($this->smtp_conn);
if ($info['timed_out']) {
$this->edebug(
@ -1192,7 +1277,7 @@ class SMTP
);
break;
}
// Now check if reads took too long
//Now check if reads took too long
if ($endtime && time() > $endtime) {
$this->edebug(
'SMTP -> get_lines(): timelimit reached (' .

38
core/class/phpmailer/phpmailer.lang-fr.php

@ -0,0 +1,38 @@
<?php
/**
* French PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
* Some French punctuation requires a thin non-breaking space (U+202F) character before it,
* for example before a colon or exclamation mark.
* There is one of these characters between these quotes: ""
* @see http://unicode.org/udhr/n/notes_fra.html
*/
$PHPMAILER_LANG['authenticate'] = 'Erreur SMTP: échec de l’authentification.';
$PHPMAILER_LANG['buggy_php'] = 'Votre version de PHP est affectée par un bug qui peut entraîner des messages corrompus. Pour résoudre ce problème, passez à l’envoi par SMTP, désactivez l’option mail.add_x_header dans le fichier php.ini, passez à MacOS ou Linux, ou passez PHP à la version 7.0.17+ ou 7.1.3+.';
$PHPMAILER_LANG['connect_host'] = 'Erreur SMTP: impossible de se connecter au serveur SMTP.';
$PHPMAILER_LANG['data_not_accepted'] = 'Erreur SMTP: données incorrectes.';
$PHPMAILER_LANG['empty_message'] = 'Corps du message vide.';
$PHPMAILER_LANG['encoding'] = 'Encodage inconnu: ';
$PHPMAILER_LANG['execute'] = 'Impossible de lancer l’exécution: ';
$PHPMAILER_LANG['extension_missing'] = 'Extension manquante: ';
$PHPMAILER_LANG['file_access'] = 'Impossible d’accéder au fichier: ';
$PHPMAILER_LANG['file_open'] = 'Ouverture du fichier impossible: ';
$PHPMAILER_LANG['from_failed'] = 'L’adresse d’expéditeur suivante a échoué: ';
$PHPMAILER_LANG['instantiate'] = 'Impossible d’instancier la fonction mail.';
$PHPMAILER_LANG['invalid_address'] = 'Adresse courriel non valide: ';
$PHPMAILER_LANG['invalid_header'] = 'Nom ou valeur de l’en-tête non valide';
$PHPMAILER_LANG['invalid_hostentry'] = 'Entrée d’hôte non valide: ';
$PHPMAILER_LANG['invalid_host'] = 'Hôte non valide: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' client de messagerie non supporté.';
$PHPMAILER_LANG['provide_address'] = 'Vous devez fournir au moins une adresse de destinataire.';
$PHPMAILER_LANG['recipients_failed'] = 'Erreur SMTP:les destinataires suivants ont échoué: ';
$PHPMAILER_LANG['signing'] = 'Erreur de signature: ';
$PHPMAILER_LANG['smtp_code'] = 'Code SMTP: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Informations supplémentaires SMTP: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'La fonction SMTP connect() a échouée.';
$PHPMAILER_LANG['smtp_detail'] = 'Détails: ';
$PHPMAILER_LANG['smtp_error'] = 'Erreur du serveur SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Impossible d’initialiser ou de réinitialiser une variable: ';
$PHPMAILER_LANG['extension_missing'] = 'Extension manquante: ';

28
core/class/template.class.php

@ -1,6 +1,6 @@
<?php
class template {
class template {
/**
* Crée un bouton
@ -118,7 +118,7 @@ class template {
copy ('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$firstNumber] . '.png', 'site/tmp/' . $firstLetter . '.png');
copy ('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$secondNumber] . '.png', 'site/tmp/' . $secondLetter . '.png');
// Début du wrapper
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="captcha inputWrapper ' . $attributes['classWrapper'] . '">';
// Label
@ -447,7 +447,7 @@ class template {
$lang = 'fr';
}
}
return '<img class="flag" src="' . helper::baseUrl(false) . 'core/vendor/i18n/png/' . $lang . '.png"
return '<img class="flag" src="' . helper::baseUrl(false) . 'core/vendor/i18n/png/' . $lang . '.png"
width="' . $size .'"
height="' . $size .'"
title="' . $lang .'"
@ -612,19 +612,17 @@ class template {
'label' => '',
'name' => $nameId,
'selected' => '',
'fonts' => false
'fonts' => []
], $attributes);
// Stocker les fontes et remettre à zéro le tableau des fontes transmis pour éviter une erreur de sprintAttributes
if (empty($attributes['fonts']) === false) {
$fonts = $attributes['fonts'];
$attributes['fonts'] = [];
}
// Sauvegarde des données en cas d'erreur
if($attributes['before'] AND array_key_exists($attributes['id'], common::$inputBefore)) {
$attributes['selected'] = common::$inputBefore[$attributes['id']];
}
// Liste des polices à intégrer
//var_dump(core::$fonts);
if ($attributes['fonts'] === true) {
foreach (core::$fonts as $fontId => $font) {
echo "<link href='https://fonts.cdnfonts.com/css/" . $fontId . "' rel='stylesheet' type='text/css'>\n";
}
}
// Début du wrapper
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
// Label
@ -633,7 +631,7 @@ class template {
'help' => $attributes['help']
]);
}
// Notice
// Notice
$notice = '';
if(array_key_exists($attributes['id'], common::$inputNotices)) {
$notice = common::$inputNotices[$attributes['id']];
@ -645,12 +643,14 @@ class template {
helper::sprintAttributes($attributes)
);
foreach($options as $value => $text) {
$html .= $attributes['fonts'] === true ? sprintf(
// Select des liste de fontes
$html .= isset($fonts) ? sprintf(
'<option value="%s"%s style="font-family: %s;">%s</option>',
$value,
$attributes['selected'] == $value ? ' selected' : '', // Double == pour ignorer le type de variable car $_POST change les types en string
core::$fonts[$value],
$fonts[$value],
$text
// Select standard
) : sprintf(
'<option value="%s"%s>%s</option>',
$value,

11
core/core.js.php

@ -215,8 +215,7 @@ core.start = function() {
// Variables des cookies
var getUrl = window.location;
var domain = "domain=" + getUrl.host + ";";
var path = "path=" + getUrl.pathname.split('/')[1] + ";";
//var path = "path=" + getUrl.pathname.split('/')[1] + ";";
var e = new Date();
e.setFullYear(e.getFullYear() + 1);
var expires = "expires=" + e.toUTCString();
@ -225,18 +224,18 @@ core.start = function() {
var analytics = "<?php echo $this->getData(['config', 'seo', 'analyticsId']);?>";
// l'Id GA est défini dans la configuration, afficher la checkbox d'acceptation
if( analytics.length > 0){
// Traitement du retour de la checkbox
// Traitement du retour de la checkbox
if ($("#googleAnalytics").is(":checked")) {
// L'URL du serveur faut TRUE
document.cookie = "ZWII_COOKIE_GA_CONSENT=true;samesite=strict;" + domain + path + expires;
document.cookie = "ZWII_COOKIE_GA_CONSENT=true;samesite=strict;" + domain + expires;
} else {
document.cookie = "ZWII_COOKIE_GA_CONSENT=false;samesite=strict;" + domain + path + expires;
document.cookie = "ZWII_COOKIE_GA_CONSENT=false;samesite=strict;" + domain + expires;
}
}
// Stocke le cookie d'acceptation
document.cookie = "ZWII_COOKIE_CONSENT=true;samesite=strict;" + domain + path + expires;
document.cookie = "ZWII_COOKIE_CONSENT=true;samesite=strict;" + domain + expires;
});

302
core/core.php

@ -45,7 +45,7 @@ class common {
// Numéro de version
const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/update/raw/branch/master/';
const ZWII_VERSION = '11.3.07';
const ZWII_VERSION = '11.4.00';
const ZWII_UPDATE_CHANNEL = "v11";
public static $actions = [];
@ -65,8 +65,8 @@ class common {
'theme',
'config',
'edit',
'config',
'translate'
'translate',
'addon'
];
public static $accessExclude = [
'login',
@ -183,39 +183,80 @@ class common {
];
// Fontes
public static $fonts = [
'abril-fatface' => 'Abril Fatface',
'arimo' => 'Arimo',
'arvo' => 'Arvo',
'berkshire-swash' => 'Berkshire Swash',
'dancing-script' => 'Dancing Script',
'droid-sans-2' => 'Droid Sans',
'droid-serif-2' => 'Droid Serif',
'fira-sans' => 'Fira Sans',
'genera' => 'Genera',
'inconsolata-2' => 'Inconsolata',
'indie-flower' => 'Indie Flower',
'josefin-sans-std' => 'Josefin Sans',
'liberation-sans' => 'Liberation Sans',
'liberation-serif' => 'Liberation Serif',
'lobster-2' => 'Lobster',
'lora' => 'Lora',
'lato' => 'Lato',
'montserrat-ace' => 'Montserrat Ace',
'old-standard-tt-3' => 'Old Standard TT',
'open-sans' => 'Open Sans',
'oswald-4' => 'Oswald',
'pt-mono' => 'PT Mono',
'pt-serif' => 'PT Serif',
'raleway-5' => 'Raleway',
'rancho' => 'Rancho',
'roboto' => 'Roboto',
'signika' => 'Signika',
'ubuntu' => 'Ubuntu',
'vollkorn' => 'Vollkorn'
public static $fontsWebSafe = [
'arial' => [
'name' => 'Arial',
'font-family' => 'Arial, Helvetica, sans-serif',
'resource' => 'websafe'
],
'arvo'=> [
'name' => 'Arvo',
'font-family' => 'Arvo, sans-serif',
'resource' => 'websafe'
],
'courrier-new' => [
'name' => 'Courier New',
'font-family' => '\'Courier New\', Courier, monospace',
'resource' => 'websafe'
],
'garamond' => [
'name' => 'Garamond',
'font-family' => 'Garamond, serif',
'resource' => 'websafe'
],
'georgia' => [
'name' => 'Geogia',
'font-family' => 'Georgia, serif',
'resource' => 'websafe'
],
'impact' => [
'name' => 'Impact',
'font-family' => 'Impact, Charcoal, sans-serif',
'resource' => 'websafe'
],
'lora'=> [
'name' => 'Lora',
'font-family' => 'Lora, serif',
'resource' => 'websafe'
],
'lucida' => [
'name' => 'Lucida',
'font-family' => '\'Lucida Sans Unicode\', \'Lucida Grande\', sans-serif',
'resource' => 'websafe'
],
'roboto'=> [
'name' => 'Roboto',
'font-family' => 'Roboto, sans-serif',
'resource' => 'websafe'
],
'tahoma' => [
'name' => 'Tahoma',
'font-family' => 'Tahoma, Geneva, sans-serif',
'resource' => 'websafe'
],
'times-new-roman' => [
'name' => 'Times New Roman',
'font-family' => '\'Times New Roman\', \'Liberation Serif\', serif',
'resource' => 'websafe'
],
'trebuchet' => [
'name' => 'Trebuchet',
'font-family' => '\'Trebuchet MS\', Arial, Helvetica, sans-serif',
'resource' => 'websafe'
],
'tahoma' => [
'name' => 'Tahoma',
'font-family' => 'Tahoma, Geneva, sans-serif',
'resource' => 'websafe'
],
'verdana' => [
'name' => 'Verdana',
'font-family' => 'Verdana, Geneva, sans-serif;',
'resource' => 'websafe'
]
];
/**
* Constructeur commun
*/
@ -250,7 +291,6 @@ class common {
]);;
}
// Import version 9
if (file_exists(self::DATA_DIR . 'core.json') === true &&
$this->getData(['core','dataVersion']) < 10000) {
@ -267,7 +307,9 @@ class common {
// La langue d'installation par défaut est fr
foreach ($this->dataFiles as $stageId => $item) {
$folder = $this->dataPath ($stageId, self::$i18n);
if (file_exists($folder . $stageId .'.json') === false) {
if ( file_exists($folder . $stageId .'.json') === false ||
$this->getData([$stageId]) === NULL
) {
$this->initData($stageId, self::$i18n);
common::$coreNotices [] = $stageId ;
}
@ -517,7 +559,6 @@ class common {
if (
$this->getData(['page', $page, 'content']) !== ''
&& file_exists(self::DATA_DIR . $lang . '/content/' . $this->getData(['page', $page, 'content']))
&& is_file(self::DATA_DIR . $lang . '/content/' . $this->getData(['page', $page, 'content']))
) {
return file_get_contents(self::DATA_DIR . $lang . '/content/' . $this->getData(['page', $page, 'content']));
} else {
@ -825,10 +866,9 @@ class common {
/**
* Génère un fichier json avec la liste des pages
*
* Génère la liste des pages pour le plugin Link de TinyMCE
*/
public function pages2Json() {
public function listPages() {
// Sauve la liste des pages pour TinyMCE
$parents = [];
$rewrite = (helper::checkRewrite()) ? '' : '?';
@ -914,8 +954,6 @@ class common {
public function createSitemap($command = "all") {
//require_once "core/vendor/sitemap/SitemapGenerator.php";
$timezone = $this->getData(['config','timezone']);
$outputDir = getcwd();
$sitemap = new \Icamys\SitemapGenerator\SitemapGenerator(helper::baseurl(false),$outputDir);
@ -1080,6 +1118,7 @@ class common {
$layout = ob_get_clean();
$mail = new PHPMailer\PHPMailer\PHPMailer;
$mail->CharSet = 'UTF-8';
$mail->setLanguage('fr', 'core/class/phpmailer/phpmailer.lang-fr.php');
// Mail
try{
// Paramètres SMTP
@ -1129,10 +1168,10 @@ class common {
else {
return $mail->ErrorInfo;
}
} catch (phpmailerException $e) {
return $e->errorMessage();
} catch (Exception $e) {
return $e->getMessage();
echo $e->errorMessage();
} catch (\Exception $e) {
echo $e->getMessage();
}
}
@ -1254,7 +1293,7 @@ class common {
$item .= '<h3>'. $this->getData(['locale', 'cookies', 'titleLabel']) . '</h3>';
$item .= '<p>' . $this->getData(['locale', 'cookies', 'mainLabel']) . '</p>';
// Formulaire de réponse
$item .= '<form method="POST" action="" id="cookieForm">';
$item .= '<form method="POST" action="' . helper::baseUrl(false, true) . '" id="cookieForm">';
$analytics = $this->getData(['config', 'seo', 'analyticsId']);
$stateCookieGA = $this->getInput('ZWII_COOKIE_GA_CONSENT') === 'true' ? 'checked="checked"' : '';
if( $analytics !== null AND $analytics !== '' ) {
@ -1342,9 +1381,6 @@ class common {
*/
echo '<div class="'. $content . '" id="contentSite">';
$this->showContent();
if (file_exists(self::DATA_DIR . 'body.inc.html')) {
include(self::DATA_DIR . 'body.inc.html');
}
echo '</div>';
/**
* Barre droite
@ -1646,7 +1682,7 @@ class common {
) {
echo '<link rel="shortcut icon" media="(prefers-color-scheme:dark)" href="' . helper::baseUrl(false) . self::FILE_DIR.'source/' . $faviconDark . '">';
//echo '<script src="https://unpkg.com/favicon-switcher@1.2.2/dist/index.js" crossorigin="anonymous" type="application/javascript"></script>';
echo '<script src="' . helper::baseUrl(false) . 'core/vendor/favicon-switcher/favicon-switcher.js" crossorigin="anonymous" type="application/javascript"></script>';
echo '<script src="' . helper::baseUrl(false) . 'core/vendor/favicon-switcher/favicon-switcher.js" crossorigin="anonymous"></script>';
}
}
@ -2121,14 +2157,18 @@ class common {
// Import des styles liés à la page
if($this->output['style']) {
echo '<base href="' . helper::baseUrl(true) .'">';
// Import de la feuille de style des pages admin
if (strpos($this->output['style'], 'admin.css') >= 1 ) {
echo '<link rel="stylesheet" href="' . self::DATA_DIR . 'admin.css?' . md5_file(self::DATA_DIR .'admin.css') . '">';
}
echo '<style type="text/css">' . helper::minifyCss($this->output['style']) . '</style>';
}
// Import des fontes liées au thème
if (file_exists(self::DATA_DIR.'fonts/fonts.html')) {
include_once(self::DATA_DIR.'fonts/fonts.html');
// Import des fontes
if ( file_exists(self::DATA_DIR . 'fonts/fonts.html') ){
include_once(self::DATA_DIR . 'fonts/fonts.html');
}
if ( file_exists(self::DATA_DIR . 'fonts/fonts.css') ){
echo '<link rel="stylesheet" href="' . helper::baseUrl(false) . self::DATA_DIR . 'fonts/fonts.css?' . md5_file(self::DATA_DIR .'fonts/fonts.css') . '">';
}
}
@ -2214,7 +2254,7 @@ class common {
}
echo '<li>';
echo '<a href="' . helper::baseUrl() . 'translate/i18n/' . $key . '/' . $this->getData(['config', 'i18n',$key]) . '/' . $this->getUrl(0) . '"><img ' . $select . ' class="flag" alt="' . $value . '" src="' . helper::baseUrl(false) . 'core/vendor/i18n/png/' . $key . '.png"/></a>';
echo '<a href="' . helper::baseUrl() . 'translate/i18n/' . $key . '/' . $this->getData(['config', 'i18n',$key]) . '/' . $this->getUrl(0) . '"><img ' . $select . ' alt="' . $value . '" src="' . helper::baseUrl(false) . 'core/vendor/i18n/png/' . $key . '.png"/></a>';
echo '</li>';
}
}
@ -2277,17 +2317,6 @@ class core extends common {
}
}
// Importe les polices personnalisées
$fontsImported = $this->getData(['fonts', 'imported']);
if (is_array($fontsImported) &&
!empty ($fontsImported)
) {
// Fusionner les fonts avec les fontes installées
self::$fonts = array_merge(self::$fonts, $fontsImported);
// Tri Alphabétique
asort(self::$fonts);
}
// Crée le fichier de personnalisation avancée
if(file_exists(self::DATA_DIR.'custom.css') === false) {
file_put_contents(self::DATA_DIR.'custom.css', file_get_contents('core/module/theme/resource/custom.css'));
@ -2303,6 +2332,7 @@ class core extends common {
file_put_contents(self::DATA_DIR.'admin.css', '');
chmod(self::DATA_DIR.'admin.css', 0755);
}
// Check la version rafraichissement du theme
$cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR.'theme.css'));
if(empty($cssVersion[1]) OR $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) {
@ -2311,55 +2341,24 @@ class core extends common {
/**
* Import des polices de caractères
* A partir du CDN ou dans le dossier site/file/source/fonts
*/
$fonts = [ $this->getData(['theme', 'text', 'font']),
$this->getData(['theme', 'title', 'font']),
$this->getData(['theme', 'header', 'font']),
$this->getData(['theme', 'menu', 'font']),
$this->getData(['theme', 'footer', 'font'])
];
// Suppression des polices identiques
$fonts = array_unique($fonts);
// Lire le fichier des fontes locales
$localFonts = $this->getData(['fonts', 'files']);
/**
* Chargement des polices en ligne dans un fichier séparé
*/
$fontFile = '';
foreach ($fonts as $fontId) {
if (!array_key_exists($fontId, $localFonts) ) {
$fontFile .= '<link href="https://fonts.cdnfonts.com/css/' . $fontId .'" rel="stylesheet">';
// Supprimer l'élément des fontes chargées en ligne
unset($fonts[$fontId]);
}
}
/**
* Fontes installées localement
*/
if ( !empty($localFonts)
) {
foreach ($localFonts as $fontId => $fontName) {
// Validité du tableau :
if ( array_key_exists($fontId, self::$fonts) ||
file_exists(self::DATA_DIR . 'fonts/' . $fontName) ) {
// Chargement de la police
$css .= '@font-face {font-family:"' . self::$fonts[$fontId] . '";';
$css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'fonts/' . $fontName . '");}';
} else {
// Le fichier de font n'est pas disponible, fonte par défaut
$fonts [$fontId] = 'verdana';
$f ['files'] = $this->getData(['fonts', 'files']);
$f ['imported'] = $this->getData(['fonts', 'imported']);
$f ['websafe'] = self::$fontsWebSafe;
// Construit un tableau avec leur ID et leur famille
foreach(['websafe', 'imported', 'files'] as $type) {
if (is_array($f[$type])) {
foreach ($f[$type] as $fontId => $fontValue ) {
$fonts[$fontId] = $fontValue['font-family'];
}
}
}
// Fond du body
$colors = helper::colorVariants($this->getData(['theme', 'body', 'backgroundColor']));
// Body
$css .= 'body{font-family:"' . self::$fonts[$this->getData(['theme', 'text', 'font'])] . '",sans-serif}';
$css .= 'body{font-family:' . $fonts[$this->getData(['theme', 'text', 'font'])] . ';}';
if($themeBodyImage = $this->getData(['theme', 'body', 'image'])) {
// Image dans html pour éviter les déformations.
$css .= 'html {background-image:url("../file/source/' . $themeBodyImage . '");background-position:' . $this->getData(['theme', 'body', 'imagePosition']) . ';background-attachment:' . $this->getData(['theme', 'body', 'imageAttachment']) . ';background-size:' . $this->getData(['theme', 'body', 'imageSize']) . ';background-repeat:' . $this->getData(['theme', 'body', 'imageRepeat']) . '}';
@ -2377,7 +2376,7 @@ class core extends common {
$colors = helper::colorVariants($this->getData(['theme', 'text', 'linkColor']));
$css .= 'a{color:' . $colors['normal'] . '}';
// Couleurs de site dans TinyMCe
$css .= 'div.mce-edit-area {font-family:"' . self::$fonts[$this->getData(['theme', 'text', 'font'])] . '",sans-serif}';
$css .= 'div.mce-edit-area {font-family:' . $fonts[$this->getData(['theme', 'text', 'font'])] . ';}';
// Site dans TinyMCE
$css .= '.editorWysiwyg {background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';}';
$css .= 'span.mce-text{background-color: unset !important;}';
@ -2418,7 +2417,7 @@ class core extends common {
$css .= '.helpButton span:hover{color:' . $colors['darken'] . '}';
$css .= '.button:active,button[type=\'submit\']:active,.pagination a:active{background-color:' . $colors['veryDarken'] . '}';
$colors = helper::colorVariants($this->getData(['theme', 'title', 'textColor']));
$css .= 'h1,h2,h3,h4,h5,h6,h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:' . $colors['normal'] . ';font-family:"' . self::$fonts[$this->getData(['theme', 'title', 'font'])] . '",sans-serif;font-weight:' . $this->getData(['theme', 'title', 'fontWeight']) . ';text-transform:' . $this->getData(['theme', 'title', 'textTransform']) . '}';
$css .= 'h1,h2,h3,h4,h5,h6,h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:' . $colors['normal'] . ';font-family:' . $fonts[$this->getData(['theme', 'title', 'font'])] . ';font-weight:' . $this->getData(['theme', 'title', 'fontWeight']) . ';text-transform:' . $this->getData(['theme', 'title', 'textTransform']) . '}';
$css .= 'h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{color:' . $colors['darken'] . '}';
// Les blocs
$colors = helper::colorVariants($this->getData(['theme', 'block', 'backgroundColor']));
@ -2452,7 +2451,7 @@ class core extends common {
$css .= 'header{background-image:url("../file/source/' . $themeHeaderImage . '");background-position:' . $this->getData(['theme', 'header', 'imagePosition']) . ';background-repeat:' . $this->getData(['theme', 'header', 'imageRepeat']) . '}';
}
$colors = helper::colorVariants($this->getData(['theme', 'header', 'textColor']));
$css .= 'header span{color:' . $colors['normal'] . ';font-family:"' . self::$fonts[$this->getData(['theme', 'header', 'font'])] . '",sans-serif;font-weight:' . $this->getData(['theme', 'header', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'header', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'header', 'textTransform']) . '}';
$css .= 'header span{color:' . $colors['normal'] . ';font-family:' . $fonts[$this->getData(['theme', 'header', 'font'])] . ';font-weight:' . $this->getData(['theme', 'header', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'header', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'header', 'textTransform']) . '}';
}
// Bannière au contenu personnalisé
@ -2501,7 +2500,7 @@ class core extends common {
$css .= 'nav{padding:0 10px;}';
}
$css .= '#toggle span,#menu a{padding:' . $this->getData(['theme', 'menu', 'height']) .';font-family:"' . self::$fonts[$this->getData(['theme', 'menu', 'font'])] . '",sans-serif;font-weight:' . $this->getData(['theme', 'menu', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'menu', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'menu', 'textTransform']) . '}';
$css .= '#toggle span,#menu a{padding:' . $this->getData(['theme', 'menu', 'height']) .';font-family:' . $fonts[$this->getData(['theme', 'menu', 'font'])] . ';font-weight:' . $this->getData(['theme', 'menu', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'menu', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'menu', 'textTransform']) . '}';
// Pied de page
$colors = helper::colorVariants($this->getData(['theme', 'footer', 'backgroundColor']));
@ -2511,7 +2510,7 @@ class core extends common {
$css .= 'footer{padding:0}';
}
$css .= 'footer span, #footerText > p {color:' . $this->getData(['theme', 'footer', 'textColor']) . ';font-family:"' . self::$fonts[$this->getData(['theme', 'footer', 'font'])] . '",sans-serif;font-weight:' . $this->getData(['theme', 'footer', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'footer', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'footer', 'textTransform']) . '}';
$css .= 'footer span, #footerText > p {color:' . $this->getData(['theme', 'footer', 'textColor']) . ';font-family:' . $fonts[$this->getData(['theme', 'footer', 'font'])] . ';font-weight:' . $this->getData(['theme', 'footer', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'footer', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'footer', 'textTransform']) . '}';
$css .= 'footer {background-color:' . $colors['normal'] . ';color:' . $this->getData(['theme', 'footer', 'textColor']) . '}';
$css .= 'footer a{color:' . $this->getData(['theme', 'footer', 'textColor']) . '}';
$css .= 'footer #footersite > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}';
@ -2522,12 +2521,6 @@ class core extends common {
$css .= '#footerText > p {text-align:' . $this->getData(['theme', 'footer', 'textAlign']) . '}';
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
// Enregistre les fontes
if (!is_dir(self::DATA_DIR . 'fonts')) {
mkdir(self::DATA_DIR . 'fonts');
}
file_put_contents(self::DATA_DIR . 'fonts/fonts.html', $fontFile);
// Enregistre la personnalisation
file_put_contents(self::DATA_DIR.'theme.css', $css);
@ -2548,52 +2541,25 @@ class core extends common {
/**
* Import des polices de caractères
* A partir du CDN ou dans le dossier site/file/source/fonts
*/
$fonts = [ $this->getData(['admin', 'fontText']),
$this->getData(['admin', 'fontTitle']),
];
// Suppression des polices identiques
$fonts = array_unique($fonts);
// Lire le fichier des fontes locales
$localFonts = $this->getData(['fonts', 'files']);
/**
* Chargement des polices en ligne
*/
foreach ($fonts as $fontId) {
if (!array_key_exists($fontId, $localFonts) ) {
$css .= '@import url("https://fonts.cdnfonts.com/css/' . $fontId . '");';
// Supprimer l'élément des fontes chargées en ligne
unset($fonts[$fontId]);
}
}
/**
* Fontes installées localement
*/
if ( !empty($localFonts)
) {
foreach ($localFonts as $fontId => $fontName) {
// Validité du tableau :
if ( array_key_exists($fontId, self::$fonts) ||
file_exists(self::DATA_DIR . 'fonts/' . $fontName) ) {
// Chargement de la police
$css .= '@font-face {font-family:"' . self::$fonts[$fontId] . '";';
$css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'fonts/' . $fontName . '");}';
} else {
// Le fichier de font n'est pas disponible, fonte par défaut
$fonts [$fontId] = 'verdana';
$f ['files'] = $this->getData(['fonts', 'files']);
$f ['imported'] = $this->getData(['fonts', 'imported']);
$f ['websafe'] = self::$fontsWebSafe;
// Construit un tableau avec leur ID et leur famille
foreach(['websafe', 'imported', 'files'] as $type) {
if (is_array($f[$type])) {
foreach ($f[$type] as $fontId => $fontValue ) {
$fonts[$fontId] = $fontValue['font-family'];
}
}
}
// Thème Administration
$colors = helper::colorVariants($this->getData(['admin','backgroundColor']));
$css .= '#site{background-color:' . $colors['normal']. ';}';
$css .= '.row > div {font:' . $this->getData(['admin','fontSize']) . ' "' . self::$fonts[$this->getData(['admin','fontText'])] . '", sans-serif;}';
$css .= 'body h1, h2, h3, h4 a, h5, h6 {font-family:"' . self::$fonts[$this->getData(['admin','fontTitle'])] . '", sans-serif;color:' . $this->getData(['admin','colorTitle' ]) . ';}';
$css .= '.row > div {font:' . $fonts[$this->getData(['admin','fontText'])] . ';font-size:' . $this->getData(['admin','fontSize']) .'}';
$css .= 'body h1, h2, h3, h4 a, h5, h6 {font-family:' . $fonts[$this->getData(['admin','fontTitle'])] . ';color:' . $this->getData(['admin','colorTitle' ]) . ';}';
// TinyMCE
$css .= 'body:not(.editorWysiwyg),span .zwiico-help {color:' . $this->getData(['admin','colorText']) . ';}';
@ -2921,9 +2887,9 @@ class core extends common {
]);
}
if ($output['style']) {
$this->addOutput([
'style' => $this->output['style'] . file_get_contents($output['style'])
]);
$this->addOutput([
'style' => $this->output['style'] . file_get_contents($output['style'])
]);
}
// JS
$scriptPath = $modulePath . 'module/' . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
@ -3033,15 +2999,23 @@ class core extends common {
'content' => template::speech('La page <strong>' . $accessInfo['pageId'] . '</strong> est ouverte par l\'utilisateur <strong>' . $accessInfo['userName'] . '</strong>')
]);
} else {
if ( $this->getData(['locale','page403']) !== 'none'
AND $this->getData(['page',$this->getData(['locale','page403'])]))
{
header('Location:' . helper::baseUrl() . $this->getData(['locale','page403']));
// Redirige vers la page de connexion si page de gestion demandée
if ( $this->getData(['config', 'connect', 'redirectLogin']) === true
&& in_array($this->geturl(0), self::$accessList) ) {
http_response_code(302);
header('Location:' . helper::baseUrl() . 'user/login/');
exit();
} else {
$this->addOutput([
'title' => 'Accès interdit',
'content' => template::speech('Vous n\'êtes pas autorisé à consulter cette page (erreur 403)')
]);
if ( $this->getData(['locale','page403']) !== 'none'
AND $this->getData(['page',$this->getData(['locale','page403'])]))
{
header('Location:' . helper::baseUrl() . $this->getData(['locale','page403']));
} else {
$this->addOutput([
'title' => 'Accès interdit',
'content' => template::speech('Vous n\'êtes pas autorisé à consulter cette page (erreur 403)')
]);
}
}
}
} elseif ($this->output['content'] === '') {