[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / ecrire / inc / texte.php
index c64532e..b7fcda5 100644 (file)
@@ -3,14 +3,22 @@
 /***************************************************************************\
  *  SPIP, Systeme de publication pour l'internet                           *
  *                                                                         *
- *  Copyright (c) 2001-2016                                                *
+ *  Copyright (c) 2001-2017                                                *
  *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
  *                                                                         *
  *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
  *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
 \***************************************************************************/
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+/**
+ * Gestion des textes et raccourcis SPIP
+ *
+ * @package SPIP\Core\Texte
+ **/
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
 
 include_spip('inc/texte_mini');
 include_spip('inc/lien');
@@ -20,31 +28,53 @@ include_spip('inc/lien');
  *
  */
 
-// Raccourcis dependant du sens de la langue
-function definir_raccourcis_alineas(){
-       return array('','');
+/**
+ * Raccourcis dépendant du sens de la langue
+ *
+ * @return array Tablea ('','')
+ */
+function definir_raccourcis_alineas() {
+       return array('', '');
 }
 
 
-//
-// Tableaux
-//
-// http://doc.spip.org/@traiter_tableau
+/**
+ * Traitement des raccourcis de tableaux
+ *
+ * Ne fait rien ici. Voir plugin Textwheel.
+ *
+ * @param string $bloc
+ * @return string
+ */
 function traiter_tableau($bloc) {
        return $bloc;
 }
 
 
-//
-// Traitement des listes (merci a Michael Parienti)
-//
-// http://doc.spip.org/@traiter_listes
-function traiter_listes ($texte) {
+/**
+ * Traitement des listes
+ *
+ * Ne fais rien. Voir Plugin Textwheel.
+ * (merci a Michael Parienti)
+ *
+ * @param string $texte
+ * @return string
+ */
+function traiter_listes($texte) {
        return $texte;
 }
 
-// Nettoie un texte, traite les raccourcis autre qu'URL, la typo, etc.
-// http://doc.spip.org/@traiter_raccourcis
+/**
+ * Nettoie un texte, traite les raccourcis autre qu'URL, la typo, etc.
+ *
+ * Ne fais rien ici. Voir plugin Textwheel.
+ *
+ * @pipeline_appel pre_propre
+ * @pipeline_appel post_propre
+ *
+ * @param string $letexte
+ * @return string
+ */
 function traiter_raccourcis($letexte) {
 
        // Appeler les fonctions de pre_traitement
@@ -63,63 +93,87 @@ function traiter_raccourcis($letexte) {
  * Fonctions utilisees en dehors de inc/texte
  */
 
-// afficher joliment les <script>
-// http://doc.spip.org/@echappe_js
-function echappe_js($t,$class=' class="echappe-js"') {
-       if (preg_match_all(',<script.*?($|</script.),isS', $t, $r, PREG_SET_ORDER))
-       foreach ($r as $regs)
-               $t = str_replace($regs[0],
-                       "<code$class>".nl2br(spip_htmlspecialchars($regs[0])).'</code>',
-                       $t);
+
+/**
+ * Échapper et affichier joliement les `<script` et `<iframe`...
+ *
+ * @param string $t
+ * @param string $class Attributs HTML du conteneur à ajouter
+ * @return string
+ */
+function echappe_js($t, $class = ' class = "echappe-js"') {
+       foreach (array('script', 'iframe') as $tag) {
+               if (stripos($t, "<$tag") !== false
+                       and preg_match_all(',<' . $tag . '.*?($|</' . $tag . '.),isS', $t, $r, PREG_SET_ORDER)
+               ) {
+                       foreach ($r as $regs) {
+                               $t = str_replace($regs[0],
+                                       "<code$class>" . nl2br(spip_htmlspecialchars($regs[0])) . '</code>',
+                                       $t);
+                       }
+               }
+       }
+
        return $t;
 }
 
 
-
 /**
  * Empêcher l'exécution de code PHP et JS
  *
  * Sécurité : empêcher l'exécution de code PHP, en le transformant en joli code
  * dans l'espace privé. Cette fonction est aussi appelée par propre et typo.
- * 
+ *
  * De la même manière, la fonction empêche l'exécution de JS mais selon le mode
- * de protection déclaré par la globale filtrer_javascript :
- * - -1 : protection dans l'espace privé et public
- * - 0  : protection dans l'espace public
- * - 1  : aucune protection
- * 
+ * de protection passe en argument
+ *
  * Il ne faut pas désactiver globalement la fonction dans l'espace privé car elle protège
  * aussi les balises des squelettes qui ne passent pas forcement par propre ou typo après
  * si elles sont appelées en direct
- * 
+ *
  * @param string $arg
  *     Code à protéger
+ * @param int $mode_filtre
+ *     Mode de protection
+ *       -1 : protection dans l'espace privé et public
+ *       0  : protection dans l'espace public
+ *       1  : aucune protection
+ *     utilise la valeur de la globale filtrer_javascript si non fourni
  * @return string
  *     Code protégé
-**/
-function interdire_scripts($arg) {
+ **/
+function interdire_scripts($arg, $mode_filtre=null) {
        // on memorise le resultat sur les arguments non triviaux
        static $dejavu = array();
 
        // Attention, si ce n'est pas une chaine, laisser intact
-       if (!$arg OR !is_string($arg) OR !strstr($arg, '<')) return $arg; 
+       if (!$arg or !is_string($arg) or !strstr($arg, '<')) {
+               return $arg;
+       }
+
+       if (is_null($mode_filtre) or !in_array($mode_filtre, array(-1, 0, 1))) {
+               $mode_filtre = $GLOBALS['filtrer_javascript'];
+       }
 
-       if (isset($dejavu[$GLOBALS['filtrer_javascript']][$arg])) return $dejavu[$GLOBALS['filtrer_javascript']][$arg];
+       if (isset($dejavu[$mode_filtre][$arg])) {
+               return $dejavu[$mode_filtre][$arg];
+       }
 
        // echapper les tags asp/php
-       $t = str_replace('<'.'%', '&lt;%', $arg);
+       $t = str_replace('<' . '%', '&lt;%', $arg);
 
        // echapper le php
-       $t = str_replace('<'.'?', '&lt;?', $t);
+       $t = str_replace('<' . '?', '&lt;?', $t);
 
        // echapper le < script language=php >
        $t = preg_replace(',<(script\b[^>]+\blanguage\b[^\w>]+php\b),UimsS', '&lt;\1', $t);
 
        // Pour le js, trois modes : parano (-1), prive (0), ok (1)
-       switch($GLOBALS['filtrer_javascript']) {
+       switch ($mode_filtre) {
                case 0:
-                       if (!_DIR_RESTREINT)
+                       if (!_DIR_RESTREINT) {
                                $t = echappe_js($t);
+                       }
                        break;
                case -1:
                        $t = echappe_js($t);
@@ -130,21 +184,46 @@ function interdire_scripts($arg) {
        $t = preg_replace(',<(base\b),iS', '&lt;\1', $t);
 
        // Reinserer les echappements des modeles
-       if (defined('_PROTEGE_JS_MODELES'))
-               $t = echappe_retour($t,"javascript"._PROTEGE_JS_MODELES);
-       if (defined('_PROTEGE_PHP_MODELES'))
-               $t = echappe_retour($t,"php"._PROTEGE_PHP_MODELES);
+       if (defined('_PROTEGE_JS_MODELES')) {
+               $t = echappe_retour($t, "javascript" . _PROTEGE_JS_MODELES);
+       }
+       if (defined('_PROTEGE_PHP_MODELES')) {
+               $t = echappe_retour($t, "php" . _PROTEGE_PHP_MODELES);
+       }
 
-       return $dejavu[$GLOBALS['filtrer_javascript']][$arg] = $t;
+       return $dejavu[$mode_filtre][$arg] = $t;
 }
 
-// Typographie generale
-// avec protection prealable des balises HTML et SPIP
 
-// http://doc.spip.org/@typo
-function typo($letexte, $echapper=true, $connect=null, $env=array()) {
+/**
+ * Applique la typographie générale
+ *
+ * Effectue un traitement pour que les textes affichés suivent les règles
+ * de typographie. Fait une protection préalable des balises HTML et SPIP.
+ * Transforme les balises `<multi>`
+ *
+ * @filtre
+ * @uses traiter_modeles()
+ * @uses corriger_typo()
+ * @uses echapper_faux_tags()
+ * @see  propre()
+ *
+ * @param string $letexte
+ *     Texte d'origine
+ * @param bool $echapper
+ *     Échapper ?
+ * @param string|null $connect
+ *     Nom du connecteur à la bdd
+ * @param array $env
+ *     Environnement (pour les calculs de modèles)
+ * @return string $t
+ *     Texte transformé
+ **/
+function typo($letexte, $echapper = true, $connect = null, $env = array()) {
        // Plus vite !
-       if (!$letexte) return $letexte;
+       if (!$letexte) {
+               return $letexte;
+       }
 
        // les appels directs a cette fonction depuis le php de l'espace
        // prive etant historiquement ecrit sans argment $connect
@@ -153,15 +232,16 @@ function typo($letexte, $echapper=true, $connect=null, $env=array()) {
        // les appels dans les squelettes (de l'espace prive) fournissant un $connect
        // ne seront pas perturbes
        $interdire_script = false;
-       if (is_null($connect)){
+       if (is_null($connect)) {
                $connect = '';
                $interdire_script = true;
-               $env['espace_prive'] = 1;
+               $env['espace_prive'] = test_espace_prive();
        }
 
        // Echapper les codes <html> etc
-       if ($echapper)
+       if ($echapper) {
                $letexte = echappe_html($letexte, 'TYPO');
+       }
 
        //
        // Installer les modeles, notamment images et documents ;
@@ -170,23 +250,27 @@ function typo($letexte, $echapper=true, $connect=null, $env=array()) {
        // cf. inc/lien
 
        $letexte = traiter_modeles($mem = $letexte, false, $echapper ? 'TYPO' : '', $connect, null, $env);
-       if ($letexte != $mem) $echapper = true;
+       if ($letexte != $mem) {
+               $echapper = true;
+       }
        unset($mem);
 
        $letexte = corriger_typo($letexte);
        $letexte = echapper_faux_tags($letexte);
 
        // reintegrer les echappements
-       if ($echapper)
+       if ($echapper) {
                $letexte = echappe_retour($letexte, 'TYPO');
+       }
 
        // Dans les appels directs hors squelette, securiser ici aussi
-       if ($interdire_script)
+       if ($interdire_script) {
                $letexte = interdire_scripts($letexte);
+       }
 
        // Dans l'espace prive on se mefie de tout contenu dangereux
        // https://core.spip.net/issues/3371
-       if (isset($env['espace_prive']) AND $env['espace_prive']){
+       if (isset($env['espace_prive']) and $env['espace_prive']) {
                $letexte = echapper_html_suspect($letexte);
        }
 
@@ -197,13 +281,28 @@ function typo($letexte, $echapper=true, $connect=null, $env=array()) {
 define('_TYPO_PROTEGER', "!':;?~%-");
 define('_TYPO_PROTECTEUR', "\x1\x2\x3\x4\x5\x6\x7\x8");
 
-define('_TYPO_BALISE', ",</?[a-z!][^<>]*[".preg_quote(_TYPO_PROTEGER)."][^<>]*>,imsS");
+define('_TYPO_BALISE', ",</?[a-z!][^<>]*[" . preg_quote(_TYPO_PROTEGER) . "][^<>]*>,imsS");
 
-// http://doc.spip.org/@corriger_typo
-function corriger_typo($letexte, $lang='') {
+/**
+ * Corrige la typographie
+ *
+ * Applique les corrections typographiques adaptées à la langue indiquée.
+ *
+ * @pipeline_appel pre_typo
+ * @pipeline_appel post_typo
+ * @uses corriger_caracteres()
+ * @uses corriger_caracteres()
+ *
+ * @param string $letexte Texte
+ * @param string $lang Langue
+ * @return string Texte
+ */
+function corriger_typo($letexte, $lang = '') {
 
        // Plus vite !
-       if (!$letexte) return $letexte;
+       if (!$letexte) {
+               return $letexte;
+       }
 
        $letexte = pipeline('pre_typo', $letexte);
 
@@ -221,16 +320,25 @@ function corriger_typo($letexte, $lang='') {
                }
        }
 
+       // trouver les blocs idiomes et les traiter à part
+       $letexte = extraire_idiome($ei = $letexte, $lang, true);
+       $ei = ($ei !== $letexte);
+
        // trouver les blocs multi et les traiter a part
-       $letexte = extraire_multi($e = $letexte, $lang, true);
-       $e = ($e === $letexte);
+       $letexte = extraire_multi($em = $letexte, $lang, true);
+       $em = ($em !== $letexte);
 
        // Charger & appliquer les fonctions de typographie
        $typographie = charger_fonction(lang_typo($lang), 'typographie');
        $letexte = $typographie($letexte);
 
        // Les citations en une autre langue, s'il y a lieu
-       if (!$e) $letexte = echappe_retour($letexte, 'multi');
+       if ($em) {
+               $letexte = echappe_retour($letexte, 'multi');
+       }
+       if ($ei) {
+               $letexte = echappe_retour($letexte, 'idiome');
+       }
 
        // Retablir les caracteres proteges
        $letexte = strtr($letexte, _TYPO_PROTECTEUR, _TYPO_PROTEGER);
@@ -245,35 +353,60 @@ function corriger_typo($letexte, $lang='') {
 }
 
 
-
-
-//
-// Une fonction pour fermer les paragraphes ; on essaie de preserver
-// des paragraphes indiques a la main dans le texte
-// (par ex: on ne modifie pas un <p align='center'>)
-//
-// deuxieme argument : forcer les <p> meme pour un seul paragraphe
-//
-// http://doc.spip.org/@paragrapher
-// /!\ appelee dans inc/filtres et public/composer
-function paragrapher($letexte, $forcer=true) {
+/**
+ * Paragrapher seulement
+ *
+ * /!\ appelée dans inc/filtres et public/composer
+ *
+ * Ne fait rien ici. Voir plugin Textwheel
+ *
+ * @param string $letexte
+ * @param null $forcer
+ * @return string
+ */
+function paragrapher($letexte, $forcer = true) {
        return $letexte;
 }
 
-// Harmonise les retours chariots et mange les paragraphes html
-// http://doc.spip.org/@traiter_retours_chariots
-// ne sert plus
+/**
+ * Harmonise les retours chariots et mange les paragraphes HTML
+ *
+ * Ne sert plus
+ *
+ * @param string $letexte Texte
+ * @return string Texte
+ **/
 function traiter_retours_chariots($letexte) {
        $letexte = preg_replace(",\r\n?,S", "\n", $letexte);
        $letexte = preg_replace(",<p[>[:space:]],iS", "\n\n\\0", $letexte);
        $letexte = preg_replace(",</p[>[:space:]],iS", "\\0\n\n", $letexte);
+
        return $letexte;
 }
 
 
-// Filtre a appliquer aux champs du type #TEXTE*
-// http://doc.spip.org/@propre
-function propre($t, $connect=null, $env=array()) {
+/**
+ * Transforme les raccourcis SPIP, liens et modèles d'un texte en code HTML
+ *
+ * Filtre à appliquer aux champs du type `#TEXTE*`
+ *
+ * @filtre
+ * @uses echappe_html()
+ * @uses expanser_liens()
+ * @uses traiter_raccourcis()
+ * @uses echappe_retour_modeles()
+ * @see  typo()
+ *
+ * @param string $t
+ *     Texte avec des raccourcis SPIP
+ * @param string|null $connect
+ *     Nom du connecteur à la bdd
+ * @param array $env
+ *     Environnement (pour les calculs de modèles)
+ * @return string $t
+ *     Texte transformé
+ **/
+function propre($t, $connect = null, $env = array()) {
        // les appels directs a cette fonction depuis le php de l'espace
        // prive etant historiquement ecrits sans argment $connect
        // on utilise la presence de celui-ci pour distinguer les cas
@@ -281,19 +414,19 @@ function propre($t, $connect=null, $env=array()) {
        // les appels dans les squelettes (de l'espace prive) fournissant un $connect
        // ne seront pas perturbes
        $interdire_script = false;
-       if (is_null($connect)){
+       if (is_null($connect)) {
                $connect = '';
                $interdire_script = true;
        }
 
-       if (!$t) return strval($t);
+       if (!$t) {
+               return strval($t);
+       }
 
        $t = echappe_html($t);
-       $t = expanser_liens($t,$connect, $env);
+       $t = expanser_liens($t, $connect, $env);
        $t = traiter_raccourcis($t);
        $t = echappe_retour_modeles($t, $interdire_script);
 
        return $t;
 }
-
-?>