diff --git a/ecrire/inc_articles_ortho.php b/ecrire/inc_articles_ortho.php index d07b7ac8a03dae988f138b21c2a01bbbfd15ed82..28e6b6e9143feb36ca7ece756a429d8d3d758a89 100644 --- a/ecrire/inc_articles_ortho.php +++ b/ecrire/inc_articles_ortho.php @@ -171,11 +171,10 @@ foreach ($champs as $champ) { case 'descriptif': case 'ps': // Mettre de cote les <code>, <cadre>, etc. - list($$champ, $echap) = echappe_html($$champ, "ORTHO"); + $$champ = echappe_html($$champ,'ORTHO'); $$champ = propre($$champ); break; default: - $echap = ""; $$champ = typo($$champ); break; } @@ -185,8 +184,7 @@ foreach ($champs as $champ) { $$champ = souligner_ortho($$champ, $lang_article, $result_ortho); // Et on repasse dans le charset original pour remettre les echappements $$champ = afficher_ortho($$champ); - if ($echap) - $$champ = echappe_retour($$champ, $echap, "ORTHO"); + $$champ = echappe_retour($$champ, 'ORTHO'); } // Traitement identique pour les notes de bas de page if ($les_notes) { diff --git a/ecrire/inc_documents.php3 b/ecrire/inc_documents.php3 index 3df613a7ba618fc39260351ed72396efae0b8b48..e538b61e0d4eec34ad4b3040b010090de33dc9d3 100644 --- a/ecrire/inc_documents.php3 +++ b/ecrire/inc_documents.php3 @@ -26,19 +26,18 @@ function vignette_par_defaut($type_extension, $size=true) { if (!$type_extension) $type_extension = 'txt'; - $filename = _DIR_IMG_ICONES . "$type_extension"; + $filename = _DIR_IMG_ICONES . $type_extension; - // Glurps ! - // je dirais meme plus: Glurps ! (esj) + // Chercher la vignette correspondant a ce type de document if (!@file_exists($v = $filename.'.png')) if (!@file_exists($v = $filename.'.gif')) if (!@file_exists($v = $filename.'-dist.png')) if (!@file_exists($v = $filename.'-dist.gif')) - if (!@file_exists($v = _DIR_IMG_ICONES . "/defaut.png")) - if (!@file_exists($v = _DIR_IMG_ICONES . "/defaut.gif")) - if (!@file_exists($v = _DIR_IMG_ICONES . "/defaut-dist.png")) - if (!@file_exists($v = _DIR_IMG_ICONES . "/defaut-dist.gif")) - $v = _DIR_IMG_ICONES . "/defaut-dist.gif"; + if (!@file_exists($v = _DIR_IMG_ICONES . "defaut.png")) + if (!@file_exists($v = _DIR_IMG_ICONES . "defaut.gif")) + if (!@file_exists($v = _DIR_IMG_ICONES . "defaut-dist.png")) + if (!@file_exists($v = _DIR_IMG_ICONES . "defaut-dist.gif")) + $v = _DIR_IMG_ICONES . "defaut-dist.gif"; if (!$size) return $v; @@ -51,6 +50,20 @@ function vignette_par_defaut($type_extension, $size=true) { } +// Quels documents a-t-on deja vu ? (gestion des doublons dans l'espace prive) +function document_vu($id_document=0) { + static $vu = array(); + + if (_DIR_RESTREINT) + return; + + if ($id_document) + $vu[$id_document]++; + else + return join(',', array_keys($vu)); +} + + // // Affiche le document avec sa vignette par defaut // @@ -111,9 +124,8 @@ function document_et_vignette($document, $url, $portfolio=false) { // function embed_document($id_document, $les_parametres="", $afficher_titre=true) { - global $id_doublons; + document_vu($id_document); charger_generer_url(); - $id_doublons['documents'] .= ",$id_document"; if ($les_parametres) { $parametres = explode("|",$les_parametres); @@ -243,9 +255,8 @@ function embed_document($id_document, $les_parametres="", $afficher_titre=true) // function integre_image($id_document, $align, $type_aff) { - global $id_doublons; + document_vu($id_document); charger_generer_url(); - $id_doublons['documents'] .= ",$id_document"; $s = spip_query("SELECT * FROM spip_documents WHERE id_document = " . intval($id_document)); @@ -376,6 +387,11 @@ function integre_image($id_document, $align, $type_aff) { // Traitement des images et documents <IMGxx|right> pour inc_texte // function inserer_documents($letexte, $matches) { + # HACK: empecher les boucles infernales lorsqu'un document est mentionne + # dans son propre descriptif (on peut citer un document dans un autre, + # mais il faut pas trop pousser...) + static $pile = 0; + if (++$pile > 5) return ''; foreach ($matches as $match) { $type = strtoupper($match[1]); @@ -384,29 +400,32 @@ function inserer_documents($letexte, $matches) { else $rempl = integre_image($match[2], $match[4], $type); - // Remplacer par une <div onclick> le lien dans le cas [<docXX>->lien] - // (si le document est deja une <div> et pas une simple image) car sinon - // on est illegal en XHTML + // XHTML : remplacer par une <div onclick> le lien + // dans le cas [<docXX>->lien] (en fait, on recherche + // <a href="lien"><docXX></a> ; sachant qu'il n'existe + // pas de bonne solution en XHTML pour produire un lien + // sur une div (!!)...) if (preg_match(',<div ,', $rempl) - AND - preg_match_all( + AND preg_match_all( ',<a\s[^>]*>([^>]*'.preg_quote($match[0]).'[^>]*)</a>,ims', - $letexte, $mm, PREG_SET_ORDER)) + $letexte, $mm, PREG_SET_ORDER)) { foreach ($mm as $m) { $url = extraire_attribut($m[0],'href'); $re = '<div onclick="document.location=\''.$url .'\'"' -## .' href="'.$url.'"' # note: href sera legal en XHTML2 +## .' href="'.$url.'"' # note: href deviendrait legal en XHTML2 .'>' .$m[0] # $m[1] si on veut eliminer le <a> (tidy le fait) ."</div>\n"; $letexte = str_replace($m[0], $re, $letexte); } + } // Installer le document $letexte = str_replace($match[0], $rempl, $letexte); } + $pile--; return $letexte; } @@ -595,7 +614,8 @@ function construire_upload($corps, $args, $action, $enc='') $res .= "\n<input type='hidden' name='$k' value='$v' />"; $res .= "\n<input type='hidden' name='action' value='joindre' />"; - $link = new Link ($action); + $link = new Link ($action); # ici enlever $action pour uploader directemet dans l'espace prive (UPLOAD_DIRECT) +# $link = new Link (); return "\n" . $link->getForm('POST', '', $enc) . "<div>" . $res . $corps . "</div></form>"; @@ -647,7 +667,7 @@ function afficher_portfolio( ) { charger_generer_url(); global $connect_id_auteur, $connect_statut; - global $id_doublons, $options, $couleur_foncee; + global $options, $couleur_foncee; global $spip_lang_left, $spip_lang_right; // la derniere case d'une rangee @@ -789,16 +809,18 @@ entites_html($document['fichier'])."\" />\n"; $query = '?id_article='.$document['id_article']; if ($document['id_rubrique']) $query = '?id_rubrique='.$document['id_rubrique']; + $query .= '&show_docs='.$id_document; echo $link->getForm('POST', "$query#$album"); echo "<b>"._T('titre_titre_document')."</b><br />\n"; echo "<input type='text' onFocus=\"changeVisible(true, 'valider_doc$id_document', 'block', 'block');\" name='titre_document' class='formo' style='font-size:11px;' value=\"".entites_html($titre)."\" size='40'><br />\n"; - // modifier la date (seulement dans les rubriques - et encore) - if ($type == 'rubrique' - AND $options == "avancees" - AND $connect_statut == '0minirezo') { - if (ereg("([0-9]{4})-([0-9]{2})-([0-9]{2})", $date, $regs)) { + // modifier la date + if ( + #$type == 'rubrique' AND // (seulement dans les rubriques?) + $options == "avancees" AND + $connect_statut == '0minirezo') { + if (ereg("([0-9]{4})-([0-9]{2})-([0-9]{2})", $date, $regs)){ $mois = $regs[2]; $jour = $regs[3]; $annee = $regs[1]; @@ -852,7 +874,7 @@ entites_html($document['fichier'])."\" />\n"; echo "</tr>\n"; } - $id_doublons['documents'] .= ",$id_document"; + document_vu($id_document); } // fermer la derniere ligne @@ -927,7 +949,7 @@ function bloc_gerer_vignette($document, $image_url, $redirect_url, $album) { function afficher_documents_non_inclus($id_article, $type = "article", $flag_modif) { global $couleur_claire; global $connect_id_auteur, $connect_statut; - global $id_doublons, $options; + global $options; global $spip_lang_left, $spip_lang_right; $image_url = generer_url_ecrire('../spip_image', @@ -946,7 +968,8 @@ function afficher_documents_non_inclus($id_article, $type = "article", $flag_mod "AND docs.mode='document'". " AND docs.id_type=lestypes.id_type AND lestypes.extension IN ('gif', 'jpg', 'png')"; - if ($id_doublons['documents']) $query .= " AND docs.id_document NOT IN (0".$id_doublons['documents'].") "; + if ($doublons = document_vu()) + $query .= " AND docs.id_document NOT IN ($doublons) "; $query .= " ORDER BY docs.id_document"; // @@ -975,7 +998,9 @@ function afficher_documents_non_inclus($id_article, $type = "article", $flag_mod "WHERE l.id_$type=$id_article AND l.id_document=docs.id_document ". "AND docs.mode='document'"; - if ($id_doublons['documents']) $query .= " AND docs.id_document NOT IN (0".$id_doublons['documents'].") "; + if ($doublons = document_vu()) + $query .= " AND docs.id_document NOT IN ($doublons) "; + $query .= " ORDER BY docs.id_document"; $documents_lies = spip_query($query); @@ -1031,8 +1056,8 @@ function afficher_documents_colonne($id_article, $type="article", $flag_modif = $image_url = generer_url_ecrire('../spip_image', (!$id_article ? "" : ('id_article='.$id_article))); - # HACK!!! simule une mise en page pour affecter la globale id_doublons - # referencee dans afficher_case_document appelee plus loin : + # HACK!!! simule une mise en page pour affecter les document_vu() + # utilises dans afficher_case_document appelee plus loin : # utile pour un affichage differencie des image "libres" et des images # integrees via <imgXX|left> dans le texte propre($GLOBALS['descriptif']." ".$GLOBALS['texte']." ".$GLOBALS['chapo']); @@ -1129,13 +1154,12 @@ function afficher_case_document($id_document, $image_url, $redirect_url = "", $d global $connect_id_auteur, $connect_statut; global $clean_link; global $options; - global $id_doublons; global $couleur_foncee, $spip_lang_left, $spip_lang_right; charger_generer_url(); $flag_deplie = teste_doc_deplie($id_document); - $doublons = $id_doublons['documents'].","; + $doublons = ','.document_vu().','; if (!$redirect_url) $redirect_url = $clean_link->getUrl(); @@ -1168,6 +1192,7 @@ function afficher_case_document($id_document, $image_url, $redirect_url = "", $d // if ($mode == 'document') { + echo "<a id='document$id_document' name='document$id_document'></a>\n"; $titre_cadre = lignes_longues(typo($titre).typo($titre_fichier), 30); debut_cadre_enfonce("doc-24.gif", false, "", $titre_cadre); @@ -1251,14 +1276,18 @@ function afficher_case_document($id_document, $image_url, $redirect_url = "", $d $link->addVar('modif_document', 'oui'); $link->addVar('id_document', $id_document); $link->addVar('show_docs', $id_document); - echo $link->getForm('POST'); + + echo $link->getForm('POST', + $clean_link->getUrl()."#document$id_document"); echo "<b>"._T('entree_titre_document')."</b><br />\n"; - echo "<input type='text' name='titre_document' class='formo' value=\"".entites_html($titre)."\" size='40'><br />\n"; + echo "<input type='text' name='titre_document' class='formo' value=\"".entites_html($titre)."\" size='40' + onFocus=\"changeVisible(true, 'valider_doc$id_document', 'block', 'block');\"><br />\n"; if ($descriptif OR $options == "avancees") { echo "<b>"._T('info_description_2')."</b><br />\n"; - echo "<textarea name='descriptif_document' rows='4' class='formo' cols='*' wrap='soft'>"; + echo "<textarea name='descriptif_document' rows='4' class='formo' cols='*' wrap='soft' + onFocus=\"changeVisible(true, 'valider_doc$id_document', 'block', 'block');\">"; echo entites_html($descriptif); echo "</textarea>\n"; } @@ -1266,7 +1295,7 @@ function afficher_case_document($id_document, $image_url, $redirect_url = "", $d if ($options == "avancees") afficher_formulaire_taille($document, $type_inclus); - echo "<div align='".$GLOBALS['spip_lang_right']."'>"; + echo "<div class='display_au_chargement' id='valider_doc$id_document' align='".$GLOBALS['spip_lang_right']."'>"; echo "<input TYPE='submit' class='fondo' style='font-size:9px;' ' VALUE='"._T('bouton_enregistrer')."'>"; echo "</div>"; echo "</form>"; diff --git a/ecrire/inc_filtres.php3 b/ecrire/inc_filtres.php3 index c7f469e5c2a65807aa24d22fdfd4f43fb958a8cc..4be7b34a06d137a063275bf986c71c99da8dad95 100644 --- a/ecrire/inc_filtres.php3 +++ b/ecrire/inc_filtres.php3 @@ -606,15 +606,22 @@ function affdate_heure($numdate) { // -// Alignements en HTML +// Alignements en HTML (Old-style, preferer CSS) // -function aligner($letexte,$justif) { - $letexte = eregi_replace("<p([^>]*)", "<p\\1 align='$justif'", trim($letexte)); - if ($letexte AND !ereg("^[[:space:]]*<p", $letexte)) { - $letexte = "<p class='spip' align='$justif'>" . $letexte . "</p>"; - } - return $letexte; +// Cette fonction cree le paragraphe s'il n'existe pas (texte sur un seul para) +function aligner($letexte, $justif='') { + $letexte = trim($letexte); + if (!strlen($letexte)) return ''; + + // Ajouter un paragraphe au debut, et reparagrapher proprement + $letexte = paragrapher( + str_replace('</p>', '', '<p>'.$letexte)); + + // Inserer les alignements + return str_replace( + '<p class="spip">', '<p class="spip" align="'.$justif.'">', + $letexte); } function justifier($letexte) { @@ -1425,7 +1432,7 @@ function extra($letexte, $champ) { function post_autobr($texte, $delim="\n_ ") { $texte = str_replace("\r\n", "\r", $texte); $texte = str_replace("\r", "\n", $texte); - list($texte, $les_echap) = echappe_html($texte, "POSTAUTOBR", true); + $texte = echappe_html($texte, '', true); $debut = ''; $suite = $texte; @@ -1444,7 +1451,7 @@ function post_autobr($texte, $delim="\n_ ") { } $texte = $debut.$suite; - $texte = echappe_retour($texte, $les_echap, "POSTAUTOBR"); + $texte = echappe_retour($texte); return $texte; } diff --git a/ecrire/inc_math.php3 b/ecrire/inc_math.php3 index fd23012e5a930fdeb79bf593aa8f2be3d22debe8..742d719b54b8cd33640e1880217ce47e05a4f9bd 100644 --- a/ecrire/inc_math.php3 +++ b/ecrire/inc_math.php3 @@ -78,7 +78,7 @@ function image_math($tex) { // Fonction appelee par propre() s'il repere un mode <math> -function traiter_math($letexte, &$les_echap, &$num_echap, $source) { +function traiter_math($letexte, $source='') { $texte_a_voir = $letexte; while (($debut = strpos($texte_a_voir, "<math>")) !== false) { @@ -91,23 +91,27 @@ function traiter_math($letexte, &$les_echap, &$num_echap, $source) { $texte_fin = substr($texte_a_voir, $fin+strlen("</math>"), strlen($texte_a_voir)); + // Les doubles $$x^2$$ en mode 'div' while((ereg("[$][$]([^$]+)[$][$]",$texte_milieu, $regs))) { - $num_echap++; - $les_echap[$num_echap] = "\n<p class=\"spip\" style=\"text-align: center;\">".image_math($regs[1])."</p>\n"; + $echap = "\n<p class=\"spip\" style=\"text-align: center;\">".image_math($regs[1])."</p>\n"; $pos = strpos($texte_milieu, $regs[0]); - $texte_milieu = substr($texte_milieu,0,$pos)."@@SPIP_$source$num_echap@@" - .substr($texte_milieu,$pos+strlen($regs[0])); + $texte_milieu = substr($texte_milieu,0,$pos) + . code_echappement($echap, 'div', $source) + . substr($texte_milieu,$pos+strlen($regs[0])); } + + // Les simples $x^2$ en mode 'span' while((ereg("[$]([^$]+)[$]",$texte_milieu, $regs))) { - $num_echap++; - $les_echap[$num_echap] = image_math($regs[1]); + $echap = image_math($regs[1]); $pos = strpos($texte_milieu, $regs[0]); - $texte_milieu = substr($texte_milieu,0,$pos)."@@SPIP_$source$num_echap@@" - .substr($texte_milieu,$pos+strlen($regs[0])); + $texte_milieu = substr($texte_milieu,0,$pos) + . code_echappement($echap, 'span', $source) + . substr($texte_milieu,$pos+strlen($regs[0])); } $texte_a_voir = $texte_debut.$texte_milieu.$texte_fin; } + return $texte_a_voir; } diff --git a/ecrire/inc_texte.php3 b/ecrire/inc_texte.php3 index 70d7cd1c0a311dbccd4d2772e422401ca68d0975..e4367b514c8fb2315cac9be41ef9d99a392729f1 100644 --- a/ecrire/inc_texte.php3 +++ b/ecrire/inc_texte.php3 @@ -65,106 +65,119 @@ function nettoyer_chapo($chapo){ // -// Mise de cote des echappements +// Echapper les les elements perilleux en les passant en base64 // -// Definition de la regexp de echappe_html -define ('__regexp_echappe', - "/(" . "<html>((.*?))<\/html>" . ")|(" #html - . "<code>((.*?))<\/code>" . ")|(" #code - . "<(cadre|frame)>((.*?))<\/(cadre|frame)>" #cadre - . ")|(" - . "<(poesie|poetry)>((.*?))<\/(poesie|poetry)>" #poesie - . ")/si"); -define('__preg_img', ',<(img|doc|emb)([0-9]+)(\|([^>]*))?'.'>,i'); +// Inserer dans le $texte le bloc base64 correspondant a $rempl, en remplacement +// de $original ($mode=span|div ; au besoin en marquant une $source differente) +function code_echappement($rempl, $mode='span', $source='') { + // Convertir en base64 + $base64 = base64_encode($rempl); + + // Ajouter le span/div d'echappement + $nn = ($mode == 'div') ? "\n\n" : ''; + return "<$mode class=\"base64$source\">$base64</$mode>$nn"; +} -function echappe_html($letexte, $source='SOURCEPROPRE', $no_transform=false) { - if (preg_match_all(__regexp_echappe, $letexte, $matches, PREG_SET_ORDER)) +// - pour $source voir commentaire infra (echappe_retour) +// - pour $no_transform voir le filtre post_autobr dans inc_filtres.php3 +function echappe_html($letexte, $source='', $no_transform=false) { + if (preg_match_all( + ',<(html|code|cadre|frame)>(.*)</\1>,Uims', + $letexte, $matches, PREG_SET_ORDER)) foreach ($matches as $regs) { - $num_echap++; - $marqueur_echap = "@@SPIP_$source$num_echap@@"; - if ($no_transform) { // echappements bruts - $les_echap[$num_echap] = $regs[0]; + // mode d'echappement : + // <span class='base64'> . base64_encode(contenu) . </span> + // ou 'div' selon les cas, pour refermer correctement les paragraphes + $mode = 'span'; + + // echappements tels quels ? + if ($no_transform) { + $echap = $regs[0]; } - else - if ($regs[1]) { + + // sinon les traiter selon le cas + else switch(strtolower($regs[1])) { + // Echapper les <html>...</ html> - $les_echap[$num_echap] = $regs[2]; - } - else - if ($regs[4]) { - // Echapper les <code>...</ code> - $lecode = entites_html($regs[5]); + case 'html': + $echap = $regs[2]; + break; - // supprimer les sauts de ligne debut/fin (mais pas les espaces => ascii art). - $lecode = ereg_replace("^\n+|\n+$", "", $lecode); + // Echapper les <code>...</ code> + case 'code': + $echap = entites_html($regs[2]); + // supprimer les sauts de ligne debut/fin + // (mais pas les espaces => ascii art). + $echap = ereg_replace("^\n+|\n+$", "", $echap); + + // ne pas mettre le <div...> s'il n'y a qu'une ligne + if (is_int(strpos($echap,"\n"))) { + $echap = nl2br("<div style='text-align: left;' " + . "class='spip_code' dir='ltr'><code>" + .$echap."</code></div>"); + $mode = 'div'; + } else + $echap = "<span class='spip_code' " + ."dir='ltr'><code>".$echap."</code></span>"; + + $echap = str_replace("\t", + " ", $echap); + $echap = str_replace(" ", " ", $echap); + break; - // ne pas mettre le <div...> s'il n'y a qu'une ligne - if (is_int(strpos($lecode,"\n"))) { - $lecode = nl2br("<div style='text-align: left;' class='spip_code' dir='ltr'><code>".$lecode."</code></div>"); - $marqueur_echap = "</no p>$marqueur_echap<no p>"; - } else - $lecode = "<span class='spip_code' dir='ltr'><code>".$lecode."</code></span>"; + // Echapper les <cadre>...</ cadre> + case 'cadre': + case 'frame': + $echap = trim(entites_html($regs[2])); + $total_lignes = substr_count($echap, "\n") + 1; + $echap = "<form action=\"/\" method=\"get\"><div>" + ."<textarea readonly='readonly' cols='40' rows='$total_lignes' " + ."class='spip_cadre' dir='ltr'>" + .$echap + ."</textarea></div></form>"; + $mode = "div"; + break; - $lecode = str_replace("\t", " ", $lecode); - $lecode = str_replace(" ", " ", $lecode); - $les_echap[$num_echap] = $lecode; - } - else - if ($regs[7]) { - // Echapper les <cadre>...</cadre> - $lecode = trim(entites_html($regs[9])); - $total_lignes = substr_count($lecode, "\n") + 1; - - $les_echap[$num_echap] = "<form action=\"/\" method=\"get\"><div><textarea readonly='readonly' cols='40' rows='$total_lignes' class='spip_cadre' dir='ltr'>".$lecode."</textarea></div></form>"; - // Les marques ci-dessous indiquent qu'on ne veut pas paragrapher - $marqueur_echap = "\n\n</no p>$marqueur_echap<no p>\n\n"; } - else - if ($regs[12]) { - $lecode = $regs[14]; - $lecode = ereg_replace("\n[[:space:]]*\n", "\n \n",$lecode); - $lecode = str_replace("\r", "\n", $lecode); # gestion des \r a revoir ! - $lecode = "<div class=\"spip_poesie\"><div>".ereg_replace("\n+", "</div>\n<div>", $lecode)."</div></div>"; - $marqueur_echap = "\n\n</no p>$marqueur_echap<no p>\n\n"; - $les_echap[$num_echap] = propre($lecode); - } - $letexte = str_replace($regs[0], $marqueur_echap, $letexte); + $letexte = str_replace($regs[0], + code_echappement($echap, $mode, $source), + $letexte); } // Gestion du TeX - if (!(strpos($letexte, "<math>") === false)) { + if (strpos($letexte, "<math>") !== false) { include_ecrire("inc_math"); - $letexte = traiter_math($letexte, $les_echap, $num_echap, $source); + $letexte = traiter_math($letexte, $source); } - return array($letexte, $les_echap); + return $letexte; } + +// // Traitement final des echappements -function echappe_retour($letexte, $les_echap, $source='SOURCEPROPRE') { - $expr = ",@@SPIP_$source([0-9]+)@@,"; - if (preg_match_all($expr, $letexte, $regs, PREG_SET_ORDER)) { - foreach ($regs as $reg) { - $rempl = $les_echap[$reg[1]]; - $letexte = str_replace($reg[0], $rempl, $letexte); +// Rq: $source sert a faire des echappements "a soi" qui ne sont pas nettoyes +// par propre() : exemple dans ecrire/inc_articles_ortho.php, $source='ORTHO' +// ou encore dans typo() +function echappe_retour($letexte, $source='') { + if (strpos($letexte," class=\"base64$source")) { + # var_dump($letexte); ## pour les curieux + if (preg_match_all( + ',<(span|div) class="base64'.$source.'">([^<>]*)</\1>,ms', + $letexte, $regs, PREG_SET_ORDER)) { + foreach ($regs as $reg) { + $rempl = base64_decode($reg[2]); + $letexte = str_replace($reg[0], $rempl, $letexte); + } } } return $letexte; } -// fonction en cas de texte extrait d'un serveur distant: -// on ne sait pas (encore) rapatrier les documents joints - -function supprime_img($letexte) { - $message = _T('img_indisponible'); - preg_replace(__preg_img, "($message)", $letexte); - return $letexte; -} - // // Gerer les outils mb_string // @@ -278,8 +291,9 @@ function couper_intro($texte, $long) { if ($intro) $intro = $intro.' (...)'; - else - $intro = couper($texte, $long); + else { + $intro = preg_replace(',([|]\s*)+,', '; ', couper($texte, $long)); + } // supprimer un eventuel chapo redirecteur =http:/..... $intro = preg_replace(',^=[^[:space:]]+,','',$intro); @@ -294,20 +308,32 @@ function couper_intro($texte, $long) { // Securite : empecher l'execution de code PHP ou javascript ou autre malice function interdire_scripts($source) { - $source = preg_replace(",<(\%|\?|[[:space:]]*(script|base)),ims", "<\\1", $source); + $source = preg_replace(",<(\%|\?|/?[[:space:]]*(script|base)),ims", "<\\1", $source); return $source; } // Securite : utiliser SafeHTML s'il est present dans ecrire/safehtml/ function safehtml($t) { - static $a; - define_once('XML_HTMLSAX3', _DIR_RESTREINT."safehtml/classes/"); - if (@file_exists(XML_HTMLSAX3.'safehtml.php')) { - include_local(XML_HTMLSAX3.'safehtml'); - $a =& new safehtml(); - $t = $a->parse($t); + static $process, $test; + + if (!$test) { + define_once('XML_HTMLSAX3', _DIR_RESTREINT."safehtml/classes/"); + if (@file_exists(XML_HTMLSAX3.'safehtml.php')) { + include_local(XML_HTMLSAX3.'safehtml'); + $process = new safehtml(); + } + if ($process) + $test = 1; # ok + else + $test = -1; # se rabattre sur interdire_scripts + } + + if ($test > 0) { + $process->clear(); # vider le buffer _xhtml de safehtml + $t = $process->parse($t); } - return $t; + + return interdire_scripts($t); # gere le < ?php > en plus } // Correction typographique francaise @@ -336,18 +362,16 @@ function typo_fr($letexte) { $letexte = strtr($letexte, $trans); $cherche1 = array( - /* 1 '/{([^}]+)}/', */ - /* 2 */ '/((^|[^\#0-9a-zA-Z\&])[\#0-9a-zA-Z]*)\;/', - /* 3 */ '/»| --?,|:([^0-9]|$)/', - /* 4 */ '/([^<!?])([!?])/', - /* 5 */ '/«|(M(M?\.|mes?|r\.?)|[MnN]°) /' + /* 1 */ '/((^|[^\#0-9a-zA-Z\&])[\#0-9a-zA-Z]*)\;/', + /* 2 */ '/»| --?,|:([^0-9]|$)/', + /* 3 */ '/([^[<!?])([!?])/', + /* 4 */ '/«|(M(M?\.|mes?|r\.?)|[MnN]°) /' ); $remplace1 = array( - /* 1 '<i class="spip">\1</i>', */ - /* 2 */ '\1~;', - /* 3 */ '~\0', - /* 4 */ '\1~\2', - /* 5 */ '\0~' + /* 1 */ '\1~;', + /* 2 */ '~\0', + /* 3 */ '\1~\2', + /* 4 */ '\0~' ); $letexte = preg_replace($cherche1, $remplace1, $letexte); $letexte = ereg_replace(" *~+ *", "~", $letexte); @@ -397,12 +421,13 @@ function typo_en($letexte) { // // Typographie generale +// note: $echapper = false lorsqu'on appelle depuis propre() [pour accelerer] // -function typo($letexte) { - global $spip_lang; +function typo($letexte, $echapper=true) { // Echapper les codes <html> etc - list($letexte, $les_echap) = echappe_html($letexte, "SOURCETYPO"); + if ($echapper) + $letexte = echappe_html($letexte, 'TYPO'); // Appeler les fonctions de pre-traitement $letexte = pipeline('pre_typo', $letexte); @@ -416,7 +441,7 @@ function typo($letexte) { // Proteger les caracteres typographiques a l'interieur des tags html $protege = "!':;?"; $illegal = "\x1\x2\x3\x4\x5"; - if (preg_match_all("/<[a-z!][^<>!':;\?]*[!':;\?][^<>]*>/ims", + if (preg_match_all(",</?[a-z!][^<>]*[!':;\?][^<>]*>,ims", $letexte, $regs, PREG_SET_ORDER)) { foreach ($regs as $reg) { $insert = $reg[0]; @@ -436,7 +461,7 @@ function typo($letexte) { // sinon determiner la typo en fonction de la langue if (!$lang = $GLOBALS['lang_typo']) { include_ecrire('inc_lang'); - $lang = lang_typo($spip_lang); + $lang = lang_typo($GLOBALS['spip_lang']); } if ($lang == 'fr') $letexte = typo_fr($letexte); @@ -446,17 +471,34 @@ function typo($letexte) { // Retablir les caracteres proteges $letexte = strtr($letexte, $illegal, $protege); + // + // Installer les images et documents ; + // + // NOTE : dans propre() ceci s'execute avant les tableaux a cause du "|", + // et apres les liens a cause du traitement de [<imgXX|right>->URL] + if (preg_match_all(__preg_img, $letexte, $matches, PREG_SET_ORDER)) { + include_ecrire('inc_documents'); + $letexte = inserer_documents($letexte, $matches); + } + // Appeler les fonctions de post-traitement $letexte = pipeline('post_typo', $letexte); // old style if (function_exists('apres_typo')) $letexte = apres_typo($letexte); + // reintegrer les echappements + if ($echapper) + $letexte = echappe_retour($letexte, 'TYPO'); + # un message pour abs_url - on est passe en mode texte $GLOBALS['mode_abs_url'] = 'texte'; - // reintegrer les echappements - return echappe_retour($letexte, $les_echap, "SOURCETYPO"); + // Dans l'espace prive, securiser ici + if (!_DIR_RESTREINT) + $letexte = interdire_scripts($letexte); + + return $letexte; } function charger_generer_url() { @@ -581,8 +623,10 @@ function extraire_lien ($regs) { $lien_url = "mailto:".$lien_url; } - $insert = "<a href=\"$lien_url\" class=\"spip_$class_lien\"" - .">".typo($lien_texte)."</a>"; + // Preparer le texte du lien ; attention s'il contient un <div> + // (ex: [<docXX|right>->lien]), il faut etre smart + $insert = typo("<a href=\"$lien_url\" class=\"spip_$class_lien\"" + .">$lien_texte</a>"); return array($insert, $lien_url, $lien_texte); } @@ -688,12 +732,12 @@ function traiter_tableau($bloc) { $html = "<tr class=\"$class\">" . $ligne . "</tr>\n".$html; } - return "\n\n</no p><table class=\"spip\"$summary>\n" + return "\n\n<table class=\"spip\"$summary>\n" . $debut_table . "<tbody>\n" . $html . "</tbody>\n" - . "</table><no p>\n\n"; + . "</table>\n\n"; } @@ -747,8 +791,8 @@ function traiter_listes ($texte) { while ($niveau < $profond) { if ($niveau == 0) $ajout .= "\n\n"; $niveau ++; - $ajout .= "</no p>"."<$type class=\"spip\">"; - $pile_type[$niveau] = "</$type>"."<no p>"; + $ajout .= "<$type class=\"spip\">"; + $pile_type[$niveau] = "</$type>"; } $ajout .= "<li class=\"spip\">"; @@ -778,9 +822,67 @@ function traiter_listes ($texte) { return substr($texte, 0, -2); } +// Definition de la regexp des images/documents +define('__preg_img', ',<(img|doc|emb)([0-9]+)(\|([^>]*))?'.'>,i'); + +// fonction en cas de texte extrait d'un serveur distant: +// on ne sait pas (encore) rapatrier les documents joints + +function supprime_img($letexte) { + $message = _T('img_indisponible'); + preg_replace(__preg_img, "($message)", $letexte); + return $letexte; +} + + +// +// 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'>) +// +function paragrapher($letexte) { + + if (preg_match(',<p[>[:space:]],i',$letexte)) { + + // Preserver les balises-bloc (y compris "STOP P") + $blocs = 'STOP P|div|pre|ul|li|blockquote|h[1-5r]|' + .'t(able|[rdh]|body|foot)|' + .'form|object|center|marquee|address|' + .'d[ltd]|script|noscript|map|del|ins|button|fieldset'; + + // Ajouter un espace aux <p> et un "STOP P" + // transformer aussi les </p> existants en <p>, nettoyes ensuite + $letexte = preg_replace(',</?p(\s([^>]*))?'.'>,i', '<STOP P><p \2>', + '<p>'.$letexte.'<STOP P>'); + + // Fermer les paragraphes + $letexte = preg_replace( + ',(<p\s.*)(</?('.$blocs.')[>[:space:]]),Uims', + "\n\\1</p>\n\\2", $letexte); + + // Supprimer les marqueurs "STOP P" + $letexte = str_replace('<STOP P>', '', $letexte); + + // Reduire les blancs dans les <p> + $letexte = preg_replace( + ',(<p(>|\s[^>]*)>)\s*|\s*(</p[>[:space:]]),i', '\1\3', + $letexte); + + // Supprimer les <p xx></p> vides + $letexte = preg_replace(',<p\s[^>]*></p>\s*,i', '', + $letexte); + + // Renommer les paragraphes normaux avec class="spip" + $letexte = str_replace('<p >', '<p class="spip">', + $letexte); + + } + + return $letexte; +} // Nettoie un texte, traite les raccourcis spip, la typo, etc. -function traiter_raccourcis_generale($letexte) { +function traiter_raccourcis($letexte) { global $debut_intertitre, $fin_intertitre, $ligne_horizontale, $url_glossaire_externe; global $compt_note; global $marqueur_notes; @@ -796,6 +898,18 @@ function traiter_raccourcis_generale($letexte) { if (function_exists('avant_propre')) $letexte = avant_propre($letexte); + + // Gestion de la <poesie> + if (preg_match_all(",<(poesie|poetry)>(.*)<\/(poesie|poetry)>,Uims", + $letexte, $regs, PREG_SET_ORDER)) { + foreach ($regs as $reg) { + $lecode = preg_replace(",\r\n?,", "\n", $reg[2]); + $lecode = ereg_replace("\n[[:space:]]*\n", "\n \n",$lecode); + $lecode = "<div class=\"spip_poesie\">\n<div>".ereg_replace("\n+", "</div>\n<div>", trim($lecode))."</div>\n</div>\n\n"; + $letexte = str_replace($reg[0], $lecode, $letexte); + } + } + // Puce if (!$lang_dir) { include_ecrire('inc_lang'); @@ -809,8 +923,9 @@ function traiter_raccourcis_generale($letexte) { // Harmoniser les retours chariot $letexte = preg_replace(",\r\n?,", "\n", $letexte); - // Corriger HTML - $letexte = preg_replace(",</?p>,i", "\n\n\n", $letexte); + // Recuperer les para HTML + $letexte = preg_replace(",<p[>[:space:]],i", "\n\n\\0", $letexte); + $letexte = preg_replace(",</p[>[:space:]],i", "\\0\n\n", $letexte); // // Notes de bas de page @@ -838,25 +953,31 @@ function traiter_raccourcis_generale($letexte) { $mn = $marqueur_notes.'-'; $ancre = $mn.urlencode($num_note); + $lien = "<a href=\"#nb$ancre\" name=\"nh$ancre\" class=\"spip_note\">"; + // creer le popup 'title' sur l'appel de note if ($title = supprimer_tags(propre($note_texte))) { $title = $ouvre_note.$ancre.$ferme_note.$title; - $title = ' title="<html>' - . texte_backend(couper($title,80)).'</html>"'; + $title = couper($title,80); + $lien = inserer_attribut($lien, 'title', $title); } - $insert = "$ouvre_ref<a href=\"#nb$ancre\" name=\"nh$ancre\" class=\"spip_note\"$title>$num_note</a>$ferme_ref"; - $appel = "<html>$ouvre_note<a href=\"#nh$ancre\" name=\"nb$ancre\" class=\"spip_note\">$num_note</a>$ferme_note</html>"; + $insert = "$ouvre_ref$lien$num_note</a>$ferme_ref"; + + // on l'echappe + $insert = code_echappement($insert, 'span'); + + $appel = "$ouvre_note<a href=\"#nh$ancre\" name=\"nb$ancre\" class=\"spip_note\">$num_note</a>$ferme_note"; } else { $insert = ''; $appel = ''; } - // l'ajouter "brut" dans les notes + // l'ajouter "tel quel" (echappe) dans les notes if ($note_texte) { if ($mes_notes) $mes_notes .= "\n\n"; - $mes_notes .= $appel . $note_texte; + $mes_notes .= code_echappement($appel, 'span') . $note_texte; } // dans le texte, mettre l'appel de note a la place de la note @@ -882,14 +1003,17 @@ function traiter_raccourcis_generale($letexte) { $url = $url_glossaire_externe.$terme_underscore; $url = str_replace("@lang@", $GLOBALS['spip_lang'], $url); $code = '['.$terme.'->?'.$url.']'; - $letexte = str_replace($regs[0], $code, $letexte); + + // Eviter les cas particulier genre "[?!?]" + if (preg_match(',[a-z],i', $terme)) + $letexte = str_replace($regs[0], $code, $letexte); } } // // Raccourcis liens [xxx->url] (cf. fonction extraire_lien ci-dessus) - // Note : complique car c'est ici qu'on applique la typo() ! + // Note : complique car c'est ici qu'on applique typo() ! // $regexp = "|\[([^][]*)->(>?)([^]]*)\]|ms"; $inserts = array(); @@ -898,23 +1022,20 @@ function traiter_raccourcis_generale($letexte) { foreach ($matches as $regs) { list($insert) = extraire_lien($regs); $inserts[++$i] = $insert; - $letexte = str_replace($regs[0], "@@SPIP_ECHAPPE$i@@", $letexte); + $letexte = str_replace($regs[0], "@@SPIP_ECHAPPE_LIEN_$i@@", $letexte); } } - $letexte = typo($letexte); + + $letexte = typo($letexte, /* echap deja fait, accelerer */ false); + foreach ($inserts as $i => $insert) { - $letexte = str_replace("@@SPIP_ECHAPPE$i@@", $insert, $letexte); + $letexte = str_replace("@@SPIP_ECHAPPE_LIEN_$i@@", $insert, $letexte); } // // Tableaux // - // traiter le cas particulier des echappements (<doc...> par exemple) - // qui auraient provoque des \n\n</no p> devant les | des tableaux - $letexte = preg_replace(',[|]\n\n</no p>@@,','|@@', $letexte); - $letexte = preg_replace(',@@<no p>\n\n[|],','@@|', $letexte); - // ne pas oublier les tableaux au debut ou a la fin du texte $letexte = preg_replace(",^\n?[|],", "\n\n|", $letexte); $letexte = preg_replace(",\n\n+[|],", "\n\n\n\n|", $letexte); @@ -952,11 +1073,9 @@ function traiter_raccourcis_generale($letexte) { /* 9 */ "/[{]/", /* 10 */ "/[}]/", /* 11 */ "/(<br[[:space:]]*\/?".">){2,}/", - /* 12 */ "/<p>([\n]*)(<br[[:space:]]*\/?".">)+/", - /* 13 */ "/<p>/", - /* 14 "/\n/", */ - /* 15 */ "/<quote>/", - /* 16 */ "/<\/quote>/" + /* 12 */ "/<p>([\n]*(<br[[:space:]]*\/?".">)*)*/", + /* 13 */ "/<quote>/", + /* 14 */ "/<\/quote>/" ); $remplace1 = array( /* 0 */ "\n\n$ligne_horizontale\n\n", @@ -965,69 +1084,22 @@ function traiter_raccourcis_generale($letexte) { /* 3 */ "\n<br />", /* 4 */ "\n\n$debut_intertitre", /* 5 */ "$fin_intertitre\n\n", - /* 6 */ "<p class=\"spip\">", + /* 6 */ "<p>", /* 7 */ "<strong class=\"spip\">", /* 8 */ "</strong>", /* 9 */ "<i class=\"spip\">", /* 10 */ "</i>", - /* 11 */ "<p class=\"spip\">", - /* 12 */ "<p class=\"spip\">", - /* 13 */ "<p class=\"spip\">", - /* 14 " ", */ - /* 15 */ "<blockquote class=\"spip\"><p class=\"spip\">", - /* 16 */ "</blockquote><p class=\"spip\">" + /* 11 */ "<p>", + /* 12 */ "<p>", + /* 13 */ "<blockquote class=\"spip\"><p>", + /* 14 */ "</blockquote><p>" ); $letexte = preg_replace($cherche1, $remplace1, $letexte); $letexte = preg_replace("@^ <br />@", "", $letexte); - // Installer les images et documents - if (preg_match_all(__preg_img, $letexte, $matches, PREG_SET_ORDER)) { - include_ecrire("inc_documents"); - $letexte = inserer_documents($letexte, $matches); - } - - // - // Affiner les paragraphes - // - - // 1. Ajouter le paragraphe initial s'il y a lieu - if (strpos(' '.$letexte, '<p class="spip">')) - $letexte = '<p class="spip">'.$letexte; - - // 2. preserver les balises-bloc - $blocs = 'div|pre|ul|li|blockquote|h[1-5r]|table|center|' - .'tr|td|th|tbody|tfoot|form|object'; - - $letexte = preg_replace(",</?($blocs)(\s[^>]*)?/?'.'>,i", '</no p>\0<no p>', $letexte); - - // 3. Manger les <p ..></no p> - $letexte = preg_replace( - ',(<p([[:space:]][^>]*)?'.'>)?(\s*</no p>)+,ims', '', $letexte); - - // 4. Fermer les paragraphes - if (strpos(' '.$letexte, '<p class="spip">')) { - $tmp = ''; - foreach (explode('<p class="spip">', $letexte) as $paragraphe) { - if (preg_match(",<(p|/?($blocs|no p))[>[:space:]].*,ims", - $paragraphe, $reg)) - $paragraphe = str_replace($reg[0], "</p>\n\n".$reg[0], $paragraphe); - else - $paragraphe .= '</p>'; - - $paragraphe = str_replace('<p class="spip"></p>', '', - '<p class="spip">'.trim($paragraphe)); - - $tmp .= $paragraphe."\n\n"; - } - - $letexte = $tmp; - } - - // 5. Manger les <no p></p> - $letexte = preg_replace( - ',(<no p>\s*)+(</p([[:space:]][^>]*)?'.'>)?,ims', '', $letexte); - + // Fermer les paragraphes + $letexte = paragrapher($letexte); // Appeler les fonctions de post-traitement $letexte = pipeline('post_propre', $letexte); @@ -1035,33 +1107,37 @@ function traiter_raccourcis_generale($letexte) { if (function_exists('apres_propre')) $letexte = apres_propre($letexte); - return array($letexte, $mes_notes); + if ($mes_notes) traiter_les_notes($mes_notes); + + return $letexte; } -function traiter_les_notes($mes_notes, $les_echap) { - $mes_notes = propre($mes_notes, $les_echap); - if (strstr($mes_notes, '<p class="spip">')) - $mes_notes = str_replace('<p class="spip">', '<p class="spip_note">', $mes_notes); - else - $mes_notes = '<p class="spip_note">'.$mes_notes."</p>\n"; +function traiter_les_notes($mes_notes) { + $mes_notes = propre('<p>'.$mes_notes); + $mes_notes = str_replace( + '<p class="spip">', '<p class="spip_note">', $mes_notes); $GLOBALS['les_notes'] .= $mes_notes; } -function traiter_raccourcis($letexte, $les_echap=false) { - // echapper les <a href>, <html>...< /html>, <code>...< /code> - if (!$les_echap) - list($letexte, $les_echap) = echappe_html($letexte, "SOURCEPROPRE"); - list($letexte, $mes_notes) = traiter_raccourcis_generale($letexte); - if ($mes_notes) traiter_les_notes($mes_notes, $les_echap); - // Reinserer les echappements - return trim(echappe_retour($letexte, $les_echap, "SOURCEPROPRE")); -} // Filtre a appliquer aux champs du type #TEXTE* -function propre($letexte, $les_echap=false) { - $letexte = traiter_raccourcis($letexte, $les_echap); +function propre($letexte) { + // Echapper les <a href>, <html>...< /html>, <code>...< /code> + $letexte = echappe_html($letexte); + + // Traiter le texte + $letexte = traiter_raccourcis($letexte); + + // Reinserer les echappements + $letexte = echappe_retour($letexte); + + // Vider les espaces superflus + $letexte = trim($letexte); + + // Dans l'espace prive, securiser ici if (!_DIR_RESTREINT) $letexte = interdire_scripts($letexte); + return $letexte; } diff --git a/inc-calcul-outils.php3 b/inc-calcul-outils.php3 index 8d37f2283f88f81701a6f3731f2135f6d3aeaca7..266fb64e3b3b0d172bea1b201a8f444b58795487 100644 --- a/inc-calcul-outils.php3 +++ b/inc-calcul-outils.php3 @@ -362,7 +362,7 @@ function traiter_doublons_documents(&$doublons, $letexte) { // les balises dynamiques et EMBED ont des filtres sans arguments // car en fait ce sont des arguments pas des filtres. -// Si le besoin s'en fait sentir, il faudra récuperer la 2e moitie du tableau +// Si le besoin s'en fait sentir, il faudra recuperer la 2e moitie du tableau function argumenter_balise($fonctions, $sep) { $res = array();